{"record":{"id":"32af2c35711cf4b0","repo":"jhy/jsoup","slug":"source-ranges-must-come-from-the-same-parse","errorCode":null,"errorMessage":"Source ranges must come from the same parse","messagePattern":"Source ranges must come from the same parse","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/jsoup/nodes/Range.java","lineNumber":437,"sourceCode":"                throw new IllegalArgumentException(\"Attribute range positions must be non-negative\");\n            useLineMap(lineMap);\n            int nameIndex = attrNameStartIndex(index);\n            int valueIndex = attrValueStartIndex(index);\n            ensureAttributeCapacity(valueIndex + 2);\n            attrRanges[nameIndex] = nameStart;\n            attrRanges[nameIndex + 1] = nameEnd;\n            attrRanges[valueIndex] = valueStart;\n            attrRanges[valueIndex + 1] = valueEnd;\n        }\n\n        /**\n         Retains the first line map and rejects mixed-source ranges.\n         */\n        private void useLineMap(LineMap lineMap) {\n            if (this.lineMap == UnsetLineMap) {\n                this.lineMap = lineMap;\n            } else if (this.lineMap != lineMap) {\n                throw new IllegalArgumentException(\"Source ranges must come from the same parse\");\n            }\n        }\n\n        /**\n         Removes an attribute slot and shifts following source ranges.\n         */\n        void removeAttributeRange(int index) {\n            if (index < 0) return;\n            int[] ranges = attrRanges;\n            int removeIndex = attrNameStartIndex(index);\n            if (removeIndex >= ranges.length) return;\n\n            int nextIndex = removeIndex + AttrRangeWidth;\n            int shifted = ranges.length - nextIndex;\n            if (shifted > 0)\n                System.arraycopy(ranges, nextIndex, ranges, removeIndex, shifted);\n            Arrays.fill(ranges, ranges.length - AttrRangeWidth, ranges.length, -1);\n        }","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/jhy/jsoup/blob/9851ac5d9c576c6888910b5a51a2362bbc978959/src/main/java/org/jsoup/nodes/Range.java#L419-L455","documentation":"Internal consistency guard in Range.useLineMap: the parser attached ranges whose position data derives from more than one Document/parse. jsoup tracks character positions per parse via a single line map; once the first range's line map is retained, any subsequent range created from a different parse cannot be translated to line/column correctly. This fires when ranges from separately parsed documents (or manually fabricated Position/range data not tied to the current parse) are mixed on the same node or attribute set.","triggerScenarios":"Thrown at src/main/java/org/jsoup/nodes/Range.java:437 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure all nodes and attribute ranges come from a single Document.parse call; do not merge nodes across separately parsed documents before reading source ranges.","If combining content from multiple parses, read each document's ranges before merging, or re-parse the combined input so all ranges share one line map.","Avoid constructing Range/Position values manually unless they originate from the same parser instance's line map."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9851ac5d9c576c6888910b5a51a2362bbc978959","analyzedAt":"2026-09-08T15:22:04.931Z","contentChangedAt":"2026-09-08T15:22:04.931Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}