ssssssss-team/spider-flow · error · IndexOutOfBoundsException
Start outside of string.
Error message
Start outside of string.
What it means
The Span(String,int,int) constructor throws IndexOutOfBoundsException("Start outside of string.") when start is greater than source.length() - 1, i.e. the start offset points past the last character. The span must begin within the source text. Note this also rejects start == source.length(), so a zero-length span at the end of the source is not allowed by this constructor.
Solutions
- Ensure start <= source.length() - 1 and that the source is non-empty before constructing.
- For an EOF/end-of-input marker, build the span with end <= source.length() and start < source.length(), or add a guard for empty input.
- Handle the empty-source case explicitly before creating spans.
- Use the single-argument Span(source) constructor when the span covers the entire source.
Example fix
// before Span eof = new Span(source, source.length(), source.length()); // after Span eof = source.isEmpty() ? null : new Span(source, Math.min(source.length() - 1, start), source.length());
Defensive patterns
Strategy: validation
Validate before calling
if (source == null || source.isEmpty()) throw new IllegalArgumentException("source must be non-empty");
if (start >= source.length()) throw new IllegalArgumentException("start " + start + " outside source of length " + source.length()); Type guard
boolean canStartSpan(String source, int start) {
return source != null && !source.isEmpty() && start >= 0 && start < source.length();
} Try / catch
try {
Span span = new Span(source, start, end);
} catch (IndexOutOfBoundsException e) {
// clamp start for EOF-style spans
Span span = new Span(source, Math.max(0, source.length() - 1), source.length());
} Prevention
- Remember this constructor forbids start == source.length(): no zero-length span at the very end.
- Model EOF positions with start = source.length() - 1, end = source.length().
- Guard empty-input parsing before building any spans.
- Clamp cursor positions with Math.min(pos, source.length() - 1).
When it happens
Trigger: Calling new Span(source, start, end) where start >= source.length(), e.g. start == source.length() for an empty range at end-of-input, or an empty source string with start=0.
Common situations: Tokenizing to end of input and building an EOF span at offset source.length(); constructing spans over empty strings; parser code that carries a cursor past the last character.
Related errors
- Start must be >= 0.
- End 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/b35afbd9af5fcb21.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/Span.java:26
/** 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;View on GitHub (pinned to c799cca99c)