didi/DoKit · error · IllegalStateException

Already connected

Error message

Already connected

What it means

setFixedLengthStreamingMode(long) may only be configured before the connection is established; the wrapper checks super.connected and throws IllegalStateException("Already connected") otherwise. Streaming mode decides how the request body is transmitted (fixed-length, no in-memory buffering), so changing it mid-flight is illegal.

Source

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

            requestHeaders.add(field, value);
        }

        @Override
        public void setRequestMethod(String method) throws ProtocolException {
            if (!METHODS.contains(method)) {
                throw new ProtocolException("Expected one of " + METHODS + " but was " + method);
            }
            this.method = method;
        }

        @Override
        public void setFixedLengthStreamingMode(int contentLength) {
            setFixedLengthStreamingMode((long) contentLength);
        }

        @Override
        public void setFixedLengthStreamingMode(long contentLength) {
            if (super.connected) throw new IllegalStateException("Already connected");
            if (chunkLength > 0) throw new IllegalStateException("Already in chunked mode");
            if (contentLength < 0) throw new IllegalArgumentException("contentLength < 0");
            this.fixedContentLength = contentLength;
            super.fixedContentLength = (int) Math.min(contentLength, Integer.MAX_VALUE);
        }

        @Override
        public void onFailure(Call call, IOException e) {
            synchronized (lock) {
                this.callFailure = (e instanceof UnexpectedException) ? e.getCause() : e;
                lock.notifyAll();
            }
        }

        @Override
        public void onResponse(Call call, Response response) {
            synchronized (lock) {
                this.response = response;

View on GitHub (pinned to 626827cddb)

Solutions

  1. Call setFixedLengthStreamingMode(bodyBytes.length) immediately after openConnection(), before any other state-advancing call.
  2. Compute the exact body length up front (serialize to byte[] first if needed).
  3. If length is unknown, use setChunkedStreamingMode() — also set before connect.

Example fix

// before
OutputStream os = conn.getOutputStream();
conn.setFixedLengthStreamingMode(body.length); // ISE

// after
conn.setFixedLengthStreamingMode(body.length);
OutputStream os = conn.getOutputStream();
Defensive patterns

Strategy: validation

Validate before calling

// immediately after openConnection():
conn.setFixedLengthStreamingMode(bodyBytes.length);

Prevention

When it happens

Trigger: Calling setFixedLengthStreamingMode() after connect(), getOutputStream(), getInputStream(), or getResponseCode() has already run.

Common situations: Upload code that decides content length after opening the output stream; wrapping libraries (e.g. multipart upload helpers) that set streaming mode late.

Related errors


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