ssssssss-team/spider-flow · error · IndexOutOfBoundsException
End outside of string.
Error message
End outside of string.
What it means
CharacterStream's constructor validates that the end offset does not exceed the source string length, throwing IndexOutOfBoundsException("End outside of string."). The end is exclusive but must be <= source.length().
Solutions
- Clamp end: end = Math.min(end, source.length())
- Validate the computed range before constructing the stream
- Check whether a length constant (e.g. needle length) was added to an already-near-end index
Example fix
// before new CharacterStream(source, start, start + MAX_TOKEN); // after int end = Math.min(start + MAX_TOKEN, source.length()); new CharacterStream(source, start, end);
Defensive patterns
Strategy: validation
Validate before calling
if (end > source.length()) end = source.length();
Try / catch
try {
new CharacterStream(source, start, end);
} catch (IndexOutOfBoundsException e) {
logger.error("End {} exceeds source length {}", end, source.length());
} Prevention
- Clamp computed end offsets with Math.min(end, source.length())
- Recompute lookahead windows near end of input
- Centralize range computation in one validated helper
When it happens
Trigger: new CharacterStream(source, start, end) with end > source.length(), e.g. end computed as start + lookaheadWidth without clamping to the string length.
Common situations: Custom parsers peeking N characters ahead near end of input; arithmetic on lengths producing overshooting bounds.
Related errors
- Start must be <= end.
- Start outside of string.
- Start must be >= 0.
- No more characters in stream.
- Start must be <= end.
AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08).
Data as JSON: /api/errors/3c278adcad154d91.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/CharacterStream.java:23
/** Wraps a the content of a {@link Source} and handles traversing the contained characters. Manages a current {@link Span} via
* the {@link #startSpan()} and {@link #endSpan()} methods. */
public class CharacterStream {
private final String source;
private int index = 0;
private final int end;
private int spanStart = 0;
public CharacterStream (String source) {
this(source, 0, source.length());
}
public CharacterStream (String source, int start, int end) {
if (start > end) throw new IllegalArgumentException("Start must be <= end.");
if (start < 0) throw new IndexOutOfBoundsException("Start must be >= 0.");
if (start > Math.max(0, source.length() - 1)) throw new IndexOutOfBoundsException("Start outside of string.");
if (end > source.length()) throw new IndexOutOfBoundsException("End outside of string.");
this.source = source;
this.index = start;
this.end = end;
}
/** Returns whether there are more characters in the stream **/
public boolean hasMore () {
return index < end;
}
/** Returns the next character without advancing the stream **/
public char peek () {
if (!hasMore()) throw new RuntimeException("No more characters in stream.");
return source.charAt(index++);
}
/** Returns the next character and advance the stream **/View on GitHub (pinned to c799cca99c)