apache/flink · error · IndexOutOfBoundsException
offset: {} len: {} value.len: {}
Error message
offset: {} len: {} value.len: {} What it means
setValue(CharSequence value, int offset, int len) validates the substring range and throws IndexOutOfBoundsException on negative offset/len or when offset > value.length() - len (range past the end). Note the message has a long-standing bug: it prints 'value.len: ' + len instead of value.length(), so the reported value.len is actually the requested length — do not trust it for diagnosis.
Source
Thrown at flink-core/src/main/java/org/apache/flink/types/StringValue.java:199
* @param offset The position to start the substring.
* @param len The length of the substring.
*/
public void setValue(StringValue value, int offset, int len) {
checkNotNull(value);
setValue(value.value, offset, len);
}
/**
* Sets the value of the StringValue to a substring of the given string.
*
* @param value The new string value.
* @param offset The position to start the substring.
* @param len The length of the substring.
*/
public void setValue(CharSequence value, int offset, int len) {
checkNotNull(value);
if (offset < 0 || len < 0 || offset > value.length() - len) {
throw new IndexOutOfBoundsException(
"offset: " + offset + " len: " + len + " value.len: " + len);
}
ensureSize(len);
this.len = len;
for (int i = 0; i < len; i++) {
this.value[i] = value.charAt(offset + i);
}
this.hashCode = 0;
}
/**
* Sets the contents of this string to the contents of the given <tt>CharBuffer</tt>. The
* characters between the buffer's current position (inclusive) and the buffer's limit
* (exclusive) will be stored in this string.
*
* @param buffer The character buffer to read the characters from.
*/View on GitHub (pinned to 2f3c205e92)
Solutions
- Validate offset >= 0 && len >= 0 && offset + len <= value.length() before the call
- Prefer setValue(value.subSequence(offset, offset + len).toString()) if bounds come from untrusted computation
- Remember the exception's value.len field is bogus; log value.length() yourself
Example fix
// before sv.setValue(text, start, width); // start+width may exceed text.length() // after int end = Math.min(start + width, text.length()); sv.setValue(text, start, end - start);
Defensive patterns
Strategy: validation
Validate before calling
if (offset < 0 || len < 0 || offset > value.length() - len) {
throw new IllegalArgumentException("substring [" + offset + "," + (offset + len) + ") vs length " + value.length());
}
sv.setValue(value, offset, len); Try / catch
catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException("Bad substring range", e); } Prevention
- Clamp computed ranges with Math.min
- Log value.length() yourself — the message prints len instead
- Watch for stale offsets after the source string changes
When it happens
Trigger: Calling setValue(seq, offset, len) with offset+len exceeding seq.length(), a negative offset, or a negative len; common when computing substrings from lengths derived elsewhere (e.g. parser positions).
Common situations: Parser/lexer code carrying offsets past the input end; off-by-one in loop bounds; reusing an offset variable after the source string changed to a shorter one.
Related errors
- Byte array does not provide enough space to store requested
- Could not skip {} bytes.
- Length must be between 0 and the current length.
- Bytes must not be null
- Cannot find empty string.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/a461ea67fcba76b6.
Report an issue: GitHub.