ssssssss-team/spider-flow · error · IllegalArgumentException
Start must be <= end.
Error message
Start must be <= end.
What it means
Span represents a character range within an expression source, used for error positioning. Its start/end constructor validates bounds and throws IllegalArgumentException("Start must be <= end.") when start > end — an inverted range.
Solutions
- Verify the start and end values passed to the Span constructor
- Ensure end is set to a position found after start; if a terminator wasn't found, bail out before creating the Span
- Clamp or swap: end = Math.max(start, end)
- Prefer the single-argument Span(source) constructor for whole-source spans
Example fix
// before
Span span = new Span(source, start, endIdx); // endIdx may be -1
// after
if (endIdx < start) {
throw new IllegalArgumentException("Terminator not found after position " + start);
}
Span span = new Span(source, start, endIdx); Defensive patterns
Strategy: validation
Validate before calling
if (start > end) throw new IllegalArgumentException("Span start (" + start + ") must be <= end (" + end + ")"); Try / catch
try {
Span span = new Span(source, start, end);
} catch (IllegalArgumentException e) {
logger.error("Invalid span range: {}..{}", start, end);
} Prevention
- Bail out when a scan for a terminator fails instead of creating a bogus span
- Keep span start/end in one immutable record computed together
- Use Span(source) for whole-source spans to avoid manual bounds
- Prefer CharacterStream for scanning; derive spans only after successful matches
When it happens
Trigger: new Span(source, start, end) with start > end, typically from failed matches producing end markers before start markers or from swapped variables.
Common situations: Custom expression parsers building error spans from scan results where the terminator was not found (end left at -1 or below start); refactors swapping start/end.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Start must be <= end.
- Start must be >= 0.
- Start outside of string.
- End outside of string.
- Start must be >= 0.
AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08).
Data as JSON: /api/errors/a4b8d5c450a2d244.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/Span.java:23
public class Span {
/** the source string this span refers to **/
private final String source;
/** 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.");
View on GitHub (pinned to c799cca99c)