jhy/jsoup · error · IllegalArgumentException
Attribute range positions must be non-negative
Error message
Attribute range positions must be non-negative
What it means
Range.AttributeRange records source offsets for an attribute's name and value. Its private constructor validates all four offsets; any negative value throws IllegalArgumentException('Attribute range positions must be non-negative').
Solutions
- Validate all four offsets are >= 0 before constructing; clamp negatives to 0 or skip assigning a range
- Fix the offset computation returning -1 (e.g. indexOf miss) upstream
- Use ranges produced by jsoup's own position tracking (Parser.setTrackPosition(true)) instead of manual values
- Wrap construction in try-catch and degrade to an unpositioned attribute on failure
Example fix
// before
attr.attributeRange(lineMap, nameStart, nameEnd, valStart, valEnd); // nameStart = -1
// after
if (nameStart >= 0 && nameEnd >= 0 && valStart >= 0 && valEnd >= 0)
attr.attributeRange(lineMap, nameStart, nameEnd, valStart, valEnd); Defensive patterns
Strategy: validation
Validate before calling
boolean validAttrRange(int ns, int ne, int vs, int ve) { return ns >= 0 && ne >= 0 && vs >= 0 && ve >= 0; } Try / catch
try { attr.attributeRange(lineMap, ns, ne, vs, ve); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Attribute range")) { /* skip or default positions */ } throw e; } Prevention
- Check scanner indexOf results for -1 before use
- Validate all four offsets before assignment
- Use jsoup-generated ranges where possible
- Guard custom TreeBuilder code with offset assertions
When it happens
Trigger: Constructing an AttributeRange with a negative nameStartPos, nameEndPos, valueStartPos, or valueEndPos — typically from custom attribute-position bookkeeping or copying positions from another document.
Common situations: Custom parsers or transformer code that assigns attribute ranges, offset math that yields -1 when a token wasn't found, or mixing ranges across documents parsed without position tracking.
Related errors
AI-assisted analysis of jhy/jsoup@9851ac5d9c (2026-09-08).
Data as JSON: /api/errors/4e96fc00db530830.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/jsoup/nodes/Range.java:264
/**
Creates the untracked attribute source range sentinel.
*/
private AttributeRange() {
lineMap = UnsetLineMap;
nameStartPos = -1;
nameEndPos = -1;
valueStartPos = -1;
valueEndPos = -1;
}
/**
Creates a new AttributeRange from source offsets.
*/
private AttributeRange(LineMap lineMap, int nameStartPos, int nameEndPos, int valueStartPos, int valueEndPos) {
this.lineMap = lineMap;
if (nameStartPos < 0 || nameEndPos < 0 || valueStartPos < 0 || valueEndPos < 0)
throw new IllegalArgumentException("Attribute range positions must be non-negative");
this.nameStartPos = nameStartPos;
this.nameEndPos = nameEndPos;
this.valueStartPos = valueStartPos;
this.valueEndPos = valueEndPos;
}
/** Get the source range for the attribute's name. */
public Range nameRange() {
return isTracked() ? new Range(lineMap, nameStartPos, nameEndPos) : Range.Untracked;
}
/** Get the source range for the attribute's value. */
public Range valueRange() {
return isTracked() ? new Range(lineMap, valueStartPos, valueEndPos) : Range.Untracked;
}
/**
Tests if this attribute range has tracked name and value offsets.View on GitHub (pinned to 9851ac5d9c)