ssssssss-team/spider-flow · error · IndexOutOfBoundsException
End outside of string.
Error message
End outside of string.
What it means
The Span(String,int,int) constructor throws IndexOutOfBoundsException("End outside of string.") when end exceeds source.length(). A span cannot extend beyond the last character of the source it references. This guards the subsequent source.substring(start, end) call from failing.
Solutions
- Clamp end to source.length(): end = Math.min(end, source.length()).
- Fix the offset arithmetic that produced an out-of-range end.
- Verify the source string is the same (complete) text the offsets were computed against.
- Use the single-argument Span(source) constructor for full-source spans.
Example fix
// before Span span = new Span(source, start, start + tokenLen); // after Span span = new Span(source, start, Math.min(start + tokenLen, source.length()));
Defensive patterns
Strategy: validation
Validate before calling
if (end > source.length()) throw new IllegalArgumentException("end " + end + " exceeds source length " + source.length());
Span span = new Span(source, start, Math.min(end, source.length())); Type guard
boolean isValidSpanRange(String source, int start, int end) {
return source != null && start >= 0 && start <= end && end <= source.length() && start < source.length();
} Try / catch
try {
Span span = new Span(source, start, end);
} catch (IndexOutOfBoundsException e) {
Span span = new Span(source, start, source.length());
} Prevention
- Treat end as exclusive and always <= source.length().
- Clamp computed ends: Math.min(end, source.length()).
- Recompute offsets against the exact same source string instance used elsewhere.
- Test tokenizers against inputs ending exactly at token boundaries.
When it happens
Trigger: Calling new Span(source, start, end) with end > source.length(), typically after computing an end offset with an inclusive/exclusive mix-up or over-advancing a cursor.
Common situations: Using end = start + tokenLength where the token runs past the input; passing matched-region offsets from a regex that already account for a terminator incorrectly.
Related errors
- Start must be >= 0.
- Start outside of string.
- Start must be >= 0.
- Start must be <= end.
- The two spans do not reference the same source.
AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08).
Data as JSON: /api/errors/e26496f122f7e544.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/Span.java:27
/** start index in source string, starting at 0 **/
private int start;
/** end index in source string, exclusive, starting at 0 **/
private int end;
/** Cached String instance to reduce pressure on GC **/
private final String cachedText;
public Span (String source) {
this(source, 0, source.length());
}
public Span (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 > 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.start = start;
this.end = end;
this.cachedText = source.substring(start, end);
}
public Span (Span start, Span end) {
if (!start.source.equals(end.source)) throw new IllegalArgumentException("The two spans do not reference the same source.");
if (start.start > end.end) throw new IllegalArgumentException("Start must be <= end.");
if (start.start < 0) throw new IndexOutOfBoundsException("Start must be >= 0.");
if (start.start > start.source.length() - 1) throw new IndexOutOfBoundsException("Start outside of string.");
if (end.end > start.source.length()) throw new IndexOutOfBoundsException("End outside of string.");
this.source = start.source;
this.start = start.start;
this.end = end.end;
this.cachedText = source.substring(this.start, this.end);View on GitHub (pinned to c799cca99c)