didi/DoKit · error · IllegalArgumentException
source == null
Error message
source == null
What it means
ByteCountBufferedSinkV4 is the OkHttp 4 / okio Kotlin-era variant of DoraomonKit's chunked BufferedSink; writeAll(Source) throws IllegalArgumentException('source == null') when passed a null Source, mirroring okio's built-in argument validation. It exists because the okio API differs between OkHttp 3 and 4.
Source
Thrown at Android/dokit-okhttp-v4/src/main/java/com/didichuxing/doraemonkit/okhttp_api/ByteCountBufferedSinkV4.java:40
* <p>
* Created by jintai on 2020-10-20 16:07
* 支持4.3.0+ 4.0.0 4.1.0 4.2.0 不支持
*/
public class ByteCountBufferedSinkV4 implements BufferedSink {
private final long mByteCount;
private final Sink mOriginalSink;
private final BufferedSink mDelegate;
public ByteCountBufferedSinkV4(Sink sink, long byteCount) {
this.mOriginalSink = sink;
this.mDelegate = Okio.buffer(mOriginalSink);
this.mByteCount = byteCount;
}
@Override
public long writeAll(Source source) throws IOException {
if (source == null) throw new IllegalArgumentException("source == null");
long totalBytesRead = 0;
for (long readCount; (readCount = source.read(buffer(), mByteCount)) != -1; ) {
totalBytesRead += readCount;
emitCompleteSegments();
}
return totalBytesRead;
}
@Override
public BufferedSink write(byte[] source, int offset, int byteCount) throws IOException {
if (!isOpen()) throw new IllegalStateException("closed");
//计算出要写入的次数
long count = (long) Math.ceil((double) source.length / mByteCount);
for (int i = 0; i < count; i++) {
//让每次写入的字节数精确到mByteCount 分多次写入
long newOffset = i * mByteCount;
long writeByteCount = Math.min(mByteCount, source.length - newOffset);
buffer().write(source, (int) newOffset, (int) writeByteCount);View on GitHub (pinned to 626827cddb)
Solutions
- Null-check the Source before calling writeAll; skip for bodyless requests
- Substitute an empty Buffer for a null Source when a zero-byte write is semantically correct
- Guard at the interceptor level: if (request.body == null) skip capture entirely
Example fix
// before
byteCountSink.writeAll(responseBodySource); // null for 204/HEAD
// after
if (responseBodySource != null) {
byteCountSink.writeAll(responseBodySource);
} Defensive patterns
Strategy: validation
Validate before calling
if (source != null) { byteCountSink.writeAll(source); } Prevention
- Guard interceptor capture with request.body() != null before pulling sources
- Substitute an empty Buffer when a null Source means 'empty body'
When it happens
Trigger: Calling writeAll(source) with null — a nullable Source from an interceptor where the request/response body was absent (GET with no body, 204, HEAD) and code passed body?.source() result or a null-returning lookup straight through.
Common situations: DoraemonKit network interception on OkHttp 4 clients where body is null for bodyless requests. Java callers of the V4 wrapper forgetting null handling that Kotlin's own Buffer types would enforce via platform types.
Related errors
- source == null
- closed
- {} must not be null
- Index: " + index + ", array1 Length: 0
- Index: " + index + ", array1 Length: " + len1
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/5d686694c3987e34.
Report an issue: GitHub.