zxing/zxing · error · IllegalArgumentException
illegal character encountered: {stringRepresentation.substri
Error message
illegal character encountered: {stringRepresentation.substring(pos)} What it means
Thrown by BitMatrix.parse(String, setString, unsetString) when the parser encounters a substring at the current position that matches neither setString nor unsetString, and is not a newline/carriage-return. The exception message includes the unparsed remainder of the string from the failure point.
Source
Thrown at core/src/main/java/com/google/zxing/common/BitMatrix.java:129
if (rowLength == -1) {
rowLength = bitsPos - rowStartPos;
} else if (bitsPos - rowStartPos != rowLength) {
throw new IllegalArgumentException("row lengths do not match");
}
rowStartPos = bitsPos;
nRows++;
}
pos++;
} else if (stringRepresentation.startsWith(setString, pos)) {
pos += setString.length();
bits[bitsPos] = true;
bitsPos++;
} else if (stringRepresentation.startsWith(unsetString, pos)) {
pos += unsetString.length();
bits[bitsPos] = false;
bitsPos++;
} else {
throw new IllegalArgumentException(
"illegal character encountered: " + stringRepresentation.substring(pos));
}
}
// no EOL at end?
if (bitsPos > rowStartPos) {
if (rowLength == -1) {
rowLength = bitsPos - rowStartPos;
} else if (bitsPos - rowStartPos != rowLength) {
throw new IllegalArgumentException("row lengths do not match");
}
nRows++;
}
BitMatrix matrix = new BitMatrix(rowLength, nRows);
for (int i = 0; i < bitsPos; i++) {
if (bits[i]) {
matrix.set(i % rowLength, i / rowLength);View on GitHub (pinned to 19aa2d8254)
Solutions
- Ensure every non-newline character in stringRepresentation is covered by either setString or unsetString — verify token lengths match
- Pre-sanitize the input: remove tabs, trim BOM, normalize line endings to '\n'
- If the input uses single characters '1'/'0' or '#'/' ', pass single-character setString/unsetString
Example fix
// before
BitMatrix.parse("## ## ##\n## ## ", "## ", " ");
// token width mismatch causes illegal character
// after
BitMatrix.parse("10110\n01101", "1", "0");
// single-char tokens, clean newlines Defensive patterns
Strategy: validation
Validate before calling
static boolean isParseable(String repr, String setStr, String unsetStr) {
if (repr == null) return false;
int pos = 0;
while (pos < repr.length()) {
char c = repr.charAt(pos);
if (c == '\n' || c == '\r') { pos++; continue; }
if (repr.startsWith(setStr, pos)) { pos += setStr.length(); }
else if (repr.startsWith(unsetStr, pos)) { pos += unsetStr.length(); }
else return false;
}
return true;
} Prevention
- Ensure the set/unset token length matches the spacing in the input string
- Pre-sanitize: strip tabs, BOM, non-breaking spaces, and other invisible characters
- Use toString() output from a known-valid matrix as the reference format for parse()
When it happens
Trigger: Calling BitMatrix.parse() where setString and unsetString tokens don't cover all characters in the input — e.g., passing setString="##" and unsetString=" " (two spaces) but the input contains single characters, or the input has stray whitespace, tabs, or punctuation.
Common situations: Mismatch between the token width used in the input string and the setString/unsetString arguments (e.g., single-char input with multi-char tokens or vice versa); non-ASCII whitespace characters in the input; trailing spaces or BOM characters.
Related errors
- row lengths do not match
- Both dimensions must be greater than 0
- input matrix dimensions do not match
- Left and top must be nonnegative
- Height and width must be at least 1
AI-assisted analysis of zxing/zxing@19aa2d8254 (2026-08-14).
Data as JSON: /api/errors/84f8e1cb009ac1fe.
Report an issue: GitHub.