{"action":"created","issue":{"url":"https://api.github.com/repos/square/okhttp/issues/2895","repository_url":"https://api.github.com/repos/square/okhttp","labels_url":"https://api.github.com/repos/square/okhttp/issues/2895/labels{/name}","comments_url":"https://api.github.com/repos/square/okhttp/issues/2895/comments","events_url":"https://api.github.com/repos/square/okhttp/issues/2895/events","html_url":"https://github.com/square/okhttp/issues/2895","id":181453644,"number":2895,"title":"okhttp3.RealCall$ApplicationInterceptorChain.proceed intermittently throws NPE","user":{"login":"jaredculp","id":1700066,"avatar_url":"https://avatars.githubusercontent.com/u/1700066?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredculp","html_url":"https://github.com/jaredculp","followers_url":"https://api.github.com/users/jaredculp/followers","following_url":"https://api.github.com/users/jaredculp/following{/other_user}","gists_url":"https://api.github.com/users/jaredculp/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredculp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredculp/subscriptions","organizations_url":"https://api.github.com/users/jaredculp/orgs","repos_url":"https://api.github.com/users/jaredculp/repos","events_url":"https://api.github.com/users/jaredculp/events{/privacy}","received_events_url":"https://api.github.com/users/jaredculp/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-10-06T15:48:57Z","updated_at":"2016-10-07T13:24:00Z","closed_at":null,"body":"I'm trying to write an `Interceptor` that dynamically appends a UUID header called \"Correlation\" (used to correlate requests across microservices).\r\n\r\nThe interceptor seems to throw a NPE randomly when I execute concurrent requests.\r\n```\r\njava.util.concurrent.ExecutionException: java.lang.NullPointerException\r\n\r\n\tat java.util.concurrent.FutureTask.report(FutureTask.java:122)\r\n\tat java.util.concurrent.FutureTask.get(FutureTask.java:192)\r\n\tat TestInterceptor.test(TestInterceptor.java:82)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.lang.reflect.Method.invoke(Method.java:498)\r\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\r\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\r\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\r\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\r\n\tat okhttp3.mockwebserver.MockWebServer$2.evaluate(MockWebServer.java:156)\r\n\tat org.junit.rules.RunRules.evaluate(RunRules.java:20)\r\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\r\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\r\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\r\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\r\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\r\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\r\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\r\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\r\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\r\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:137)\r\n\tat com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)\r\n\tat com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)\r\n\tat com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)\r\n\tat com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.lang.reflect.Method.invoke(Method.java:498)\r\n\tat com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)\r\nCaused by: java.lang.NullPointerException\r\n\tat okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)\r\n\tat TestInterceptor$CorrelatedInterceptor.intercept(TestInterceptor.java:106)\r\n\tat okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)\r\n\tat okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)\r\n\tat okhttp3.RealCall.execute(RealCall.java:57)\r\n\tat retrofit2.OkHttpCall.execute(OkHttpCall.java:174)\r\n\tat TestInterceptor.lambda$test$0(TestInterceptor.java:78)\r\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\r\n\tat java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)\r\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\r\n\tat java.lang.Thread.run(Thread.java:745)\r\n```\r\n\r\nI've reproduced the issue with the following isolated test case below. The tests may pass a few times, but eventually will fail. Changing the `count` variable to `1` will make the tests pass every time, but anything larger than 1 causes intermittent failures.\r\n\r\n```java\r\nimport com.fasterxml.jackson.annotation.JsonCreator;\r\nimport com.fasterxml.jackson.annotation.JsonProperty;\r\nimport com.fasterxml.jackson.databind.ObjectMapper;\r\nimport okhttp3.HttpUrl;\r\nimport okhttp3.Interceptor;\r\nimport okhttp3.OkHttpClient;\r\nimport okhttp3.Request;\r\nimport okhttp3.mockwebserver.MockResponse;\r\nimport okhttp3.mockwebserver.MockWebServer;\r\nimport org.junit.Rule;\r\nimport org.junit.Test;\r\nimport retrofit2.Call;\r\nimport retrofit2.Response;\r\nimport retrofit2.Retrofit;\r\nimport retrofit2.converter.jackson.JacksonConverterFactory;\r\nimport retrofit2.http.GET;\r\n\r\nimport java.io.IOException;\r\nimport java.util.UUID;\r\nimport java.util.concurrent.ExecutionException;\r\nimport java.util.concurrent.ExecutorCompletionService;\r\nimport java.util.concurrent.Executors;\r\n\r\nimport static com.google.common.truth.Truth.assertThat;\r\nimport static java.util.Objects.requireNonNull;\r\n\r\npublic class TestInterceptor {\r\n\r\n    @Rule\r\n    public final MockWebServer mockWebServer = new MockWebServer();\r\n\r\n    interface MyClient {\r\n        @GET(\"/\")\r\n        Call<MyObject> get();\r\n    }\r\n\r\n    static final class MyObject {\r\n        private final UUID value;\r\n\r\n        @JsonCreator\r\n        public MyObject(@JsonProperty(\"value\") UUID value) {\r\n            this.value = value;\r\n        }\r\n\r\n        public UUID getValue() {\r\n            return this.value;\r\n        }\r\n    }\r\n\r\n    @Test\r\n    public void test() throws IOException, InterruptedException, ExecutionException {\r\n        final int count = 10;\r\n\r\n        final ObjectMapper mapper = new ObjectMapper();\r\n        final UUID correlation = UUID.randomUUID();\r\n        final MyObject myObject = new MyObject(correlation);\r\n\r\n        for (int i = 0; i < count; i++) {\r\n            this.mockWebServer.enqueue(new MockResponse()\r\n                    .setBody(mapper.writeValueAsString(myObject)));\r\n        }\r\n\r\n        final HttpUrl httpUrl = new HttpUrl.Builder()\r\n                .host(this.mockWebServer.getHostName())\r\n                .port(this.mockWebServer.getPort())\r\n                .scheme(\"http\")\r\n                .build();\r\n\r\n        final OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();\r\n        final Retrofit.Builder retrofitBuilder = retrofitBuilder(httpUrl, mapper);\r\n        final MyCorrelated myCorrelated = new MyCorrelated(okHttpBuilder, retrofitBuilder);\r\n\r\n        final ExecutorCompletionService<Response<MyObject>> executorService =\r\n                new ExecutorCompletionService<>(Executors.newFixedThreadPool(count));\r\n        for (int i = 0; i < count; i++) {\r\n            executorService.submit(() -> myCorrelated.withId(correlation).get().execute());\r\n        }\r\n\r\n        for (int i = 0; i < count; i++) {\r\n            final Response response = executorService.take().get();\r\n            assertThat(response.isSuccessful()).isTrue();\r\n\r\n            assertThat(this.mockWebServer.takeRequest().getHeader(\"Correlated\")).isEqualTo(correlation.toString());\r\n        }\r\n    }\r\n\r\n    private static final class CorrelatedInterceptor implements Interceptor {\r\n\r\n        private static final String HEADER_NAME = \"Correlated\";\r\n\r\n        private final UUID correlationId;\r\n\r\n        public CorrelatedInterceptor(UUID correlationId) {\r\n            this.correlationId = requireNonNull(correlationId, \"correlationId\");\r\n        }\r\n\r\n        @Override\r\n        public okhttp3.Response intercept(Chain chain) throws IOException {\r\n            final Request original = chain.request();\r\n            final Request reWritten = original.newBuilder()\r\n                    .addHeader(HEADER_NAME, this.correlationId.toString())\r\n                    .build();\r\n\r\n            return chain.proceed(reWritten);\r\n        }\r\n\r\n    }\r\n\r\n    private static Retrofit.Builder retrofitBuilder(HttpUrl url, ObjectMapper mapper) {\r\n        return new Retrofit.Builder().baseUrl(url).addConverterFactory(JacksonConverterFactory.create(mapper));\r\n    }\r\n\r\n    interface Correlated<T> {\r\n        T withId(UUID id);\r\n    }\r\n\r\n    private static final class MyCorrelated implements Correlated<MyClient> {\r\n\r\n        private final OkHttpClient.Builder okHttpBuilder;\r\n        private final Retrofit.Builder retrofitBuilder;\r\n\r\n        private MyCorrelated(OkHttpClient.Builder okHttpBuilder, Retrofit.Builder retrofitBuilder) {\r\n            this.okHttpBuilder = okHttpBuilder;\r\n            this.retrofitBuilder = retrofitBuilder;\r\n        }\r\n\r\n        @Override\r\n        public MyClient withId(UUID id) {\r\n            return this.retrofitBuilder\r\n                    .client(this.okHttpBuilder.addInterceptor(new CorrelatedInterceptor(id)).build())\r\n                    .build()\r\n                    .create(MyClient.class);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nIs there something obvious that I'm missing?"},"comment":{"url":"https://api.github.com/repos/square/okhttp/issues/comments/252250824","html_url":"https://github.com/square/okhttp/issues/2895#issuecomment-252250824","issue_url":"https://api.github.com/repos/square/okhttp/issues/2895","id":252250824,"user":{"login":"jaredculp","id":1700066,"avatar_url":"https://avatars.githubusercontent.com/u/1700066?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredculp","html_url":"https://github.com/jaredculp","followers_url":"https://api.github.com/users/jaredculp/followers","following_url":"https://api.github.com/users/jaredculp/following{/other_user}","gists_url":"https://api.github.com/users/jaredculp/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredculp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredculp/subscriptions","organizations_url":"https://api.github.com/users/jaredculp/orgs","repos_url":"https://api.github.com/users/jaredculp/repos","events_url":"https://api.github.com/users/jaredculp/events{/privacy}","received_events_url":"https://api.github.com/users/jaredculp/received_events","type":"User","site_admin":false},"created_at":"2016-10-07T13:24:00Z","updated_at":"2016-10-07T13:24:00Z","body":"@swankjesse here's the full output from my IDE.\r\n\r\n```\r\nOct 07, 2016 9:22:45 AM okhttp3.mockwebserver.MockWebServer$3 execute\r\nINFO: MockWebServer[56184] starting to accept connections\r\nOct 07, 2016 9:22:46 AM okhttp3.mockwebserver.MockWebServer$3 acceptConnections\r\nINFO: MockWebServer[56184] done accepting connections: Socket closed\r\n\r\njava.util.concurrent.ExecutionException: java.lang.NullPointerException\r\n\r\n\tat java.util.concurrent.FutureTask.report(FutureTask.java:122)\r\n\tat java.util.concurrent.FutureTask.get(FutureTask.java:192)\r\n\tat TestInterceptor.test(TestInterceptor.java:82)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.lang.reflect.Method.invoke(Method.java:498)\r\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\r\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\r\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\r\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\r\n\tat okhttp3.mockwebserver.MockWebServer$2.evaluate(MockWebServer.java:156)\r\n\tat org.junit.rules.RunRules.evaluate(RunRules.java:20)\r\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\r\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\r\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\r\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\r\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\r\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\r\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\r\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\r\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\r\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:137)\r\n\tat com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)\r\n\tat com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)\r\n\tat com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)\r\n\tat com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.lang.reflect.Method.invoke(Method.java:498)\r\n\tat com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)\r\nCaused by: java.lang.NullPointerException\r\n\tat okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)\r\n\tat okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)\r\n\tat okhttp3.RealCall.execute(RealCall.java:57)\r\n\tat retrofit2.OkHttpCall.execute(OkHttpCall.java:174)\r\n\tat TestInterceptor.lambda$test$0(TestInterceptor.java:78)\r\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\r\n\tat java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)\r\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\r\n\tat java.lang.Thread.run(Thread.java:745)\r\n\r\n\r\nProcess finished with exit code 255\r\n```"}}
{"actor":{"display_login":"jaredculp"}}