Summary
AfterShipClient.Builder.build() creates its RequestConfig without a cookie spec, so Apache HttpClient 4 falls back to CookieSpecs.DEFAULT. That spec cannot parse the Cloudflare __cf_bm cookie that api.aftership.com returns on every response, and org.apache.http.client.protocol.ResponseProcessCookies logs a WARN for each call.
We see ~5000 of these per day on a single worker. There is no functional impact, but it drowns the application logs.
Invalid cookie header: "set-cookie: __cf_bm=<redacted>; HttpOnly; SameSite=None; Secure; Path=/; Domain=aftership.com; Expires=Fri, 11 Sep 2026 07:52:08 GMT". Invalid 'expires' attribute: Fri, 11 Sep 2026 07:52:08 GMT
Versions
com.aftership:tracking-sdk 11.0.0 and 12.0.1 (latest) are both affected
org.apache.httpcomponents:httpclient 4.5.14, as declared by the SDK pom
Root cause
AfterShipClient.Builder.build() only sets the proxy and the socket timeout:
RequestConfig.custom()
.setProxy(...) // when a proxy is configured
.setSocketTimeout(timeoutMill)
.build();
With no cookieSpec, HttpClient 4 uses DefaultCookieSpecProvider. Because the Set-Cookie header carries an expires attribute and no version, that provider routes to the Netscape draft branch, which only accepts EEE, dd-MMM-yy HH:mm:ss z. Cloudflare emits RFC 1123 (Fri, 11 Sep 2026 07:52:08 GMT), so parsing fails.
Reproduction
Standalone, against httpclient 4.5.14 — no SDK call needed:
CookieSpec spec = new DefaultCookieSpecProvider().create(null);
CookieOrigin origin = new CookieOrigin("api.aftership.com", 443, "/", true);
Header header = new BasicHeader("Set-Cookie",
"__cf_bm=abc123; HttpOnly; SameSite=None; Secure; Path=/; Domain=aftership.com; Expires=Fri, 11 Sep 2026 07:52:08 GMT");
spec.parse(header, origin);
Output:
Invalid 'expires' attribute: Fri, 11 Sep 2026 07:52:08 GMT
The same header parses cleanly with new RFC6265CookieSpecProvider().create(null), and the default spec accepts the header once Expires is rewritten as Fri, 11-Sep-26 07:52:08 GMT.
Suggested fix
The SDK authenticates through headers and never reads cookies, so the cleanest fix is to opt out in AfterShipClient.Builder.build():
RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
// ... existing proxy and timeout
If you would rather keep cookie handling, CookieSpecs.STANDARD (RFC 6265) parses the Cloudflare cookie correctly.
Workarounds for other users
- Set
org.apache.http.client.protocol.ResponseProcessCookies to ERROR in the logging configuration.
- Or pass a pre-built client:
new AfterShipClient.Builder(...).setHttpClient(new HttpClient(requestConfig, userAgent)) with a RequestConfig that sets CookieSpecs.IGNORE_COOKIES.
Summary
AfterShipClient.Builder.build()creates itsRequestConfigwithout a cookie spec, so Apache HttpClient 4 falls back toCookieSpecs.DEFAULT. That spec cannot parse the Cloudflare__cf_bmcookie thatapi.aftership.comreturns on every response, andorg.apache.http.client.protocol.ResponseProcessCookieslogs a WARN for each call.We see ~5000 of these per day on a single worker. There is no functional impact, but it drowns the application logs.
Versions
com.aftership:tracking-sdk11.0.0 and 12.0.1 (latest) are both affectedorg.apache.httpcomponents:httpclient4.5.14, as declared by the SDK pomRoot cause
AfterShipClient.Builder.build()only sets the proxy and the socket timeout:With no
cookieSpec, HttpClient 4 usesDefaultCookieSpecProvider. Because theSet-Cookieheader carries anexpiresattribute and noversion, that provider routes to the Netscape draft branch, which only acceptsEEE, dd-MMM-yy HH:mm:ss z. Cloudflare emits RFC 1123 (Fri, 11 Sep 2026 07:52:08 GMT), so parsing fails.Reproduction
Standalone, against httpclient 4.5.14 — no SDK call needed:
Output:
The same header parses cleanly with
new RFC6265CookieSpecProvider().create(null), and the default spec accepts the header onceExpiresis rewritten asFri, 11-Sep-26 07:52:08 GMT.Suggested fix
The SDK authenticates through headers and never reads cookies, so the cleanest fix is to opt out in
AfterShipClient.Builder.build():If you would rather keep cookie handling,
CookieSpecs.STANDARD(RFC 6265) parses the Cloudflare cookie correctly.Workarounds for other users
org.apache.http.client.protocol.ResponseProcessCookiestoERRORin the logging configuration.new AfterShipClient.Builder(...).setHttpClient(new HttpClient(requestConfig, userAgent))with aRequestConfigthat setsCookieSpecs.IGNORE_COOKIES.