didi/DoKit · error · IllegalStateException

Cannot set request property after connection is made

Error message

Cannot set request property after connection is made

What it means

setRequestProperty() is only legal before the connection is established; the wrapper's 'connected' flag flips to true inside buildCall() (triggered by connect, output/input streams, response code), after which setRequestProperty throws IllegalStateException("Cannot set request property after connection is made"). This preserves the standard HttpURLConnection contract.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java:685

            if (proxy != null) return true;
            Proxy clientProxy = client.proxy();
            return clientProxy != null && clientProxy.type() != Proxy.Type.DIRECT;
        }

        @Override
        public String getResponseMessage() throws IOException {
            return getResponse(true).message();
        }

        @Override
        public int getResponseCode() throws IOException {
            return getResponse(true).code();
        }

        @Override
        public void setRequestProperty(String field, String newValue) {
            if (connected) {
                throw new IllegalStateException("Cannot set request property after connection is made");
            }
            if (field == null) {
                throw new NullPointerException("field == null");
            }
            if (newValue == null) {
                return;
            }

            requestHeaders.set(field, newValue);
        }

        @Override
        public void setIfModifiedSince(long newValue) {
            super.setIfModifiedSince(newValue);
            if (ifModifiedSince != 0) {
                requestHeaders.set("If-Modified-Since", format(new Date(ifModifiedSince)));
            } else {
                requestHeaders.removeAll("If-Modified-Since");

View on GitHub (pinned to 626827cddb)

Solutions

  1. Set all request properties before the first connect-triggering call.
  2. In retry loops, create a new connection and re-apply all headers from a saved map.
  3. Review code paths where interceptors/callbacks mutate the connection after writing starts.

Example fix

// before
conn.connect();
conn.setRequestProperty("Authorization", token); // ISE

// after
conn.setRequestProperty("Authorization", token);
conn.connect();
Defensive patterns

Strategy: validation

Validate before calling

// apply every header from a map before any connect-triggering call:
for (Map.Entry<String,String> e : headers.entrySet()) conn.setRequestProperty(e.getKey(), e.getValue());

Try / catch

try { conn.setRequestProperty(k, v); } catch (IllegalStateException ignored) { /* already connected: reopen connection instead */ }

Prevention

When it happens

Trigger: Calling setRequestProperty() (or setRequestProperty-based helpers like setIfModifiedSince after connect) once connect()/getOutputStream()/getInputStream()/getResponseCode() has run.

Common situations: Setting an Authorization header lazily inside a retry loop; interleaving header setup with streaming-body writes; auth interceptors that patch headers late.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/0d64c39aded181e3. Report an issue: GitHub.