{"record":{"id":"385aa1bd9a5209d9","repo":"didi/DoKit","slug":"no-body-found-has-createbodysink-been-called","errorCode":null,"errorMessage":"No body found; has createBodySink been called?","messagePattern":"No body found; has createBodySink been called\\?","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java","lineNumber":54,"sourceCode":"        } else {\n            deflatingOutput = deflatedOutput;\n        }\n        mDeflatedOutput = deflatedOutput;\n        return deflatingOutput;\n    }\n\n    public byte[] getDisplayBody() {\n        throwIfNoBody();\n        return mDeflatedOutput.toByteArray();\n    }\n\n    public boolean hasBody() {\n        return mDeflatedOutput != null;\n    }\n\n    private void throwIfNoBody() {\n        if (!hasBody()) {\n            throw new IllegalStateException(\"No body found; has createBodySink been called?\");\n        }\n    }\n}\n","sourceCodeStart":36,"sourceCodeEnd":58,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java#L36-L58","documentation":"Thrown by RequestBodyHelper (getDisplayBody / getContentType etc. via throwIfNoBody) when read methods are accessed before createBodySink() has initialized the internal deflated output buffer. The helper is a write-first pipeline: createBodySink() allocates mDeflatedOutput, and only then do the read accessors become legal.","triggerScenarios":"Calling getDisplayBody() before createBodySink() was ever invoked — e.g. an interceptor reading the body snapshot for a request/response where the body sink was skipped (GET requests, 304 responses, or an early return path that bypassed createBodySink).","commonSituations":"Custom interceptors that unconditionally log the display body even when the response has no body; Read paths that run after a createBodySink failure (exception swallowed, leaving hasBody() == false); Ordering bugs where the read happens on a different thread before the write side finished setup","solutions":["Guard every read with hasBody(): if (helper.hasBody()) byte[] body = helper.getDisplayBody();","Ensure createBodySink() is called on the body path before any accessor, including error paths","Fix control flow that bypasses createBodySink (early returns / exceptions between intercept and read)"],"exampleFix":"// before\nbyte[] body = requestBodyHelper.getDisplayBody(); // throws if no sink created\n\n// after\nbyte[] body = requestBodyHelper.hasBody() ? requestBodyHelper.getDisplayBody() : null;","handlingStrategy":"validation","validationCode":"if (requestBodyHelper.hasBody()) {\n    byte[] body = requestBodyHelper.getDisplayBody();\n} else {\n    // createBodySink() was never called for this request/response\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard every RequestBodyHelper accessor with hasBody()","Ensure createBodySink() runs on all body paths, including error branches, before any read"],"tags":["android","network","interceptor","state-machine"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}