{"record":{"id":"a4b8d5c450a2d244","repo":"ssssssss-team/spider-flow","slug":"start-must-be-end-a4b8d5","errorCode":null,"errorMessage":"Start must be <= end.","messagePattern":"Start must be <= end\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/Span.java","lineNumber":23,"sourceCode":"public class Span {\n\t/** the source string this span refers to **/\n\tprivate final String source;\n\n\t/** start index in source string, starting at 0 **/\n\tprivate int start;\n\n\t/** end index in source string, exclusive, starting at 0 **/\n\tprivate int end;\n\n\t/** Cached String instance to reduce pressure on GC **/\n\tprivate final String cachedText;\n\n\tpublic Span (String source) {\n\t\tthis(source, 0, source.length());\n\t}\n\n\tpublic Span (String source, int start, int end) {\n\t\tif (start > end) throw new IllegalArgumentException(\"Start must be <= end.\");\n\t\tif (start < 0) throw new IndexOutOfBoundsException(\"Start must be >= 0.\");\n\t\tif (start > source.length() - 1) \n\t\t\tthrow new IndexOutOfBoundsException(\"Start outside of string.\");\n\t\tif (end >source.length()) throw new IndexOutOfBoundsException(\"End outside of string.\");\n\n\t\tthis.source = source;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.cachedText = source.substring(start, end);\n\t}\n\n\tpublic Span (Span start, Span end) {\n\t\tif (!start.source.equals(end.source)) throw new IllegalArgumentException(\"The two spans do not reference the same source.\");\n\t\tif (start.start > end.end) throw new IllegalArgumentException(\"Start must be <= end.\");\n\t\tif (start.start < 0) throw new IndexOutOfBoundsException(\"Start must be >= 0.\");\n\t\tif (start.start > start.source.length() - 1) throw new IndexOutOfBoundsException(\"Start outside of string.\");\n\t\tif (end.end > start.source.length()) throw new IndexOutOfBoundsException(\"End outside of string.\");\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/ssssssss-team/spider-flow/blob/c799cca99c7d064673dc79e6ef06a08bbc0e292d/spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/Span.java#L5-L41","documentation":"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.","triggerScenarios":"new Span(source, start, end) with start > end, typically from failed matches producing end markers before start markers or from swapped variables.","commonSituations":"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.","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"],"exampleFix":"// before\nSpan span = new Span(source, start, endIdx); // endIdx may be -1\n// after\nif (endIdx < start) {\n    throw new IllegalArgumentException(\"Terminator not found after position \" + start);\n}\nSpan span = new Span(source, start, endIdx);","handlingStrategy":"validation","validationCode":"if (start > end) throw new IllegalArgumentException(\"Span start (\" + start + \") must be <= end (\" + end + \")\");","typeGuard":null,"tryCatchPattern":"try {\n    Span span = new Span(source, start, end);\n} catch (IllegalArgumentException e) {\n    logger.error(\"Invalid span range: {}..{}\", start, end);\n}","preventionTips":["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"],"tags":["parsing","span","bounds-check"],"backgroundTag":"invalid-argument-value","analyzedSha":"c799cca99c7d064673dc79e6ef06a08bbc0e292d","analyzedAt":"2026-09-08T13:47:08.225Z","contentChangedAt":"2026-09-08T13:47:08.225Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}