didi/DoKit · error · IllegalArgumentException
source == null
Error message
source == null
What it means
ByteCountBufferedSinkV3 is DoraemonKit's okio BufferedSink wrapper that writes in fixed mByteCount chunks (used to intercept and mirror OkHttp request/response bodies). writeAll(Source) validates its argument up front, mirroring okio's own contract, and throws IllegalArgumentException on a null source before attempting any read.
Source
Thrown at Android/dokit-okhttp-v3/src/main/java/com/didichuxing/doraemonkit/okhttp_api/ByteCountBufferedSinkV3.java:35
/**
* 可以设置每次写入大小的BufferedSink
* <p>
* Created by xiandanin on 2019-05-10 16:07
*/
public class ByteCountBufferedSinkV3 implements BufferedSink {
private final long mByteCount;
private final Sink mOriginalSink;
private final BufferedSink mDelegate;
public ByteCountBufferedSinkV3(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 and skip or substitute Buffer() (an empty Source) when null
- Fix the producer: map 'no body' to an empty okio Buffer instead of null
- In Kotlin, use 'source ?: Buffer()' or an explicit if-null guard
Example fix
// before
byteCountSink.writeAll(nullableSource);
// after
if (nullableSource != null) {
byteCountSink.writeAll(nullableSource);
} else {
byteCountSink.write(Buffer()); // or simply skip
} Defensive patterns
Strategy: validation
Validate before calling
if (source != null) { byteCountSink.writeAll(source); } else { byteCountSink.write(new okio.Buffer()); } Prevention
- Map 'no body' to an empty Buffer, not null, in interceptor code
- Skip capture entirely for bodyless requests/responses (HEAD, 204)
When it happens
Trigger: Calling writeAll(source) with null — typically when a response/request body Source resolved to null (empty body mapped to null, interceptor returning null for the body, or an upstream API returning null instead of an empty Source).
Common situations: OkHttp interceptors in DoraKit's network inspection flow where a HEAD/204 response has no body and the code passes body.source() from a null body. Third-party servers returning empty bodies handled as null. Kotlin code passing a nullable Source without a null check.
Related errors
- closed
- source == null
- {} 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/4c80bf1201a78a72.
Report an issue: GitHub.