didi/DoKit · error · IllegalArgumentException
Unexpected char %#04x at %d in %s value: %s
Error message
Unexpected char %#04x at %d in %s value: %s
What it means
Thrown by CommonHeaders.Builder.checkNameAndValue when a header VALUE contains a control character other than tab (<= U+001F) or a non-ASCII character (>= U+007F) at position i. Unlike names, values may contain tabs and spaces, but raw control or non-ASCII bytes must be encoded first.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java:292
addLenient(name, value);
return this;
}
private void checkNameAndValue(String name, String value) {
if (name == null) throw new NullPointerException("name == null");
if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
for (int i = 0, length = name.length(); i < length; i++) {
char c = name.charAt(i);
if (c <= '\u0020' || c >= '\u007f') {
throw new IllegalArgumentException(format(
"Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
}
}
if (value == null) throw new NullPointerException("value == null");
for (int i = 0, length = value.length(); i < length; i++) {
char c = value.charAt(i);
if ((c <= '\u001f' && c != '\t') || c >= '\u007f') {
throw new IllegalArgumentException(format(
"Unexpected char %#04x at %d in %s value: %s", (int) c, i, name, value));
}
}
}
/** Equivalent to {@code build().get(name)}, but potentially faster. */
public String get(String name) {
for (int i = namesAndValues.size() - 2; i >= 0; i -= 2) {
if (name.equalsIgnoreCase(namesAndValues.get(i))) {
return namesAndValues.get(i + 1);
}
}
return null;
}
public CommonHeaders build() {
return new CommonHeaders(this);
}View on GitHub (pinned to 626827cddb)
Solutions
- URL-encode (percent-encode) or Base64 any non-ASCII header value before add()
- Strip CR/LF and other control chars from values assembled from free text (also guards header injection)
- Log the failing name/value on IllegalArgumentException to identify which header carries the bad byte
Example fix
// before
builder.add("X-Note", note); // note contains '\n' or non-ASCII
// after
builder.add("X-Note", URLEncoder.encode(note, "UTF-8")); Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidHeaderValue(String v) {
if (v == null) return false;
for (int i = 0; i < v.length(); i++) {
char c = v.charAt(i);
if ((c <= '\u001f' && c != '\t') || c >= '\u007f') return false;
}
return true;
} Prevention
- URL-encode or Base64 non-ASCII values before putting them in headers
- Strip CR/LF from free-text values to prevent both this error and header injection
When it happens
Trigger: builder.add("X-Meta", "line1\nline2") (newline in value), a value containing '\0', or a value with a CJK/accented character such as add("X-Note", "失败") passed unencoded.
Common situations: JSON or binary payloads stuffed into custom header values without encoding; localized error messages copied into headers; values read from files/network that include CR/LF (also a header-injection vector).
Related errors
- Expected alternating header names and values
- Unexpected header: " + name + ": " + value
- Unexpected char %#04x at %d in header name: %s
- namesAndValues == null
- Headers cannot be null
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/b7b81682b497e774.
Report an issue: GitHub.