{"action":"closed","issue":{"url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/issues/900","labels_url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/issues/900/labels{/name}","comments_url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/issues/900/comments","events_url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/issues/900/events","html_url":"https://github.com/AsyncHttpClient/async-http-client/issues/900","id":83701302,"number":900,"title":"AHC-1.9 Netty3 provider throws NullPointerException on retry if maxConnectionsPerHost is enabled","user":{"login":"jonas-ren","id":1539669,"avatar_url":"https://avatars.githubusercontent.com/u/1539669?v=3","gravatar_id":"","url":"https://api.github.com/users/jonas-ren","html_url":"https://github.com/jonas-ren","followers_url":"https://api.github.com/users/jonas-ren/followers","following_url":"https://api.github.com/users/jonas-ren/following{/other_user}","gists_url":"https://api.github.com/users/jonas-ren/gists{/gist_id}","starred_url":"https://api.github.com/users/jonas-ren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonas-ren/subscriptions","organizations_url":"https://api.github.com/users/jonas-ren/orgs","repos_url":"https://api.github.com/users/jonas-ren/repos","events_url":"https://api.github.com/users/jonas-ren/events{/privacy}","received_events_url":"https://api.github.com/users/jonas-ren/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/labels/Defect","name":"Defect","color":"e11d21"},{"url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/labels/Netty","name":"Netty","color":"009800"}],"state":"closed","locked":false,"assignee":{"login":"slandelle","id":849197,"avatar_url":"https://avatars.githubusercontent.com/u/849197?v=3","gravatar_id":"","url":"https://api.github.com/users/slandelle","html_url":"https://github.com/slandelle","followers_url":"https://api.github.com/users/slandelle/followers","following_url":"https://api.github.com/users/slandelle/following{/other_user}","gists_url":"https://api.github.com/users/slandelle/gists{/gist_id}","starred_url":"https://api.github.com/users/slandelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slandelle/subscriptions","organizations_url":"https://api.github.com/users/slandelle/orgs","repos_url":"https://api.github.com/users/slandelle/repos","events_url":"https://api.github.com/users/slandelle/events{/privacy}","received_events_url":"https://api.github.com/users/slandelle/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/milestones/59","html_url":"https://github.com/AsyncHttpClient/async-http-client/milestones/1.9.27","labels_url":"https://api.github.com/repos/AsyncHttpClient/async-http-client/milestones/59/labels","id":1143848,"number":59,"title":"1.9.27","description":"","creator":{"login":"slandelle","id":849197,"avatar_url":"https://avatars.githubusercontent.com/u/849197?v=3","gravatar_id":"","url":"https://api.github.com/users/slandelle","html_url":"https://github.com/slandelle","followers_url":"https://api.github.com/users/slandelle/followers","following_url":"https://api.github.com/users/slandelle/following{/other_user}","gists_url":"https://api.github.com/users/slandelle/gists{/gist_id}","starred_url":"https://api.github.com/users/slandelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slandelle/subscriptions","organizations_url":"https://api.github.com/users/slandelle/orgs","repos_url":"https://api.github.com/users/slandelle/repos","events_url":"https://api.github.com/users/slandelle/events{/privacy}","received_events_url":"https://api.github.com/users/slandelle/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":1,"state":"open","created_at":"2015-06-01T22:18:58Z","updated_at":"2015-06-01T22:20:36Z","due_on":"2015-06-08T22:00:00Z","closed_at":null},"comments":0,"created_at":"2015-06-01T21:27:18Z","updated_at":"2015-06-01T22:20:36Z","closed_at":"2015-06-01T22:20:36Z","body":"In AHC-1.9, if maxConnectionsPerHost is enabled and the client is sending a second request on either retry or redirect, it will cause an NPE. Stack trace:\r\n\r\nJun 01, 2015 11:55:34 AM org.jboss.netty.channel.DefaultChannelFuture\r\nWARNING: An exception was thrown by ChannelFutureListener.\r\njava.lang.NullPointerException\r\n\tat java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)\r\n\tat java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)\r\n\tat com.ning.http.client.providers.netty.channel.ChannelManager.registerOpenChannel(ChannelManager.java:387)\r\n\tat com.ning.http.client.providers.netty.request.NettyConnectListener.writeRequest(NettyConnectListener.java:80)\r\n\tat com.ning.http.client.providers.netty.request.NettyConnectListener.onFutureSuccess(NettyConnectListener.java:107)\r\n\tat com.ning.http.client.providers.netty.request.NettyConnectListener.operationComplete(NettyConnectListener.java:138)\r\n        at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:431)\r\n\tat org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:422)\r\n\tat org.jboss.netty.channel.DefaultChannelFuture.setSuccess(DefaultChannelFuture.java:362)\r\n\tat org.jboss.netty.channel.socket.nio.NioWorker$RegisterTask.run(NioWorker.java:156)\r\n\tat org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)\r\n\tat org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)\r\n\tat org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)\r\n\tat org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)\r\n\tat org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)\r\n\tat org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)\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\nI investigated a bit and seems like the root cause is that NettyRequestSender doesn't set partitionKey if reclaimCache is true (always true on retry). See: https://github.com/AsyncHttpClient/async-http-client/blob/master/providers/netty3/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java#L266-285\r\n\r\nThis is causing paritionKey to passed as null to ChannelManager, which throws NPE on put to ConcurrentMap. See: https://github.com/AsyncHttpClient/async-http-client/blob/master/providers/netty3/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java#L298\r\n\r\nSince the ConcurrentMap expect both key and value not to be null, I think it's not unlikely for it to throw NPE on some other cases. Feels like we should be more strict about key/value null checking here."}}