{"record":{"id":"e85268fd8df3c9b1","repo":"antlr/antlr4","slug":"replace-op-boundaries-of-rop-overlap-with-previ","errorCode":null,"errorMessage":"replace op boundaries of ${rop} overlap with previous ${prevRop}","messagePattern":"replace op boundaries of (.+?) overlap with previous (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"runtime/JavaScript/src/antlr4/TokenStreamRewriter.js","lineNumber":259,"sourceCode":"            let prevReplaces = this.getKindOfOps(rewrites, ReplaceOp, i);\n            for (let prevRop of prevReplaces) {\n                if (prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex) {\n                    // delete replace as it's a no-op.\n                    rewrites[prevRop.instructionIndex] = undefined;\n                    continue;\n                }\n                // throw exception unless disjoint or identical\n                let disjoint =\n                    prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex;\n                // Delete special case of replace (text==null):\n                // D.i-j.u D.x-y.v\t| boundaries overlap\tcombine to max(min)..max(right)\n                if (prevRop.text == null && rop.text == null && !disjoint) {\n                    rewrites[prevRop.instructionIndex] = undefined; // kill first delete\n                    rop.index = Math.min(prevRop.index, rop.index);\n                    rop.lastIndex = Math.max(prevRop.lastIndex, rop.lastIndex);\n                }\n                else if (!disjoint) {\n                    throw new Error(`replace op boundaries of ${rop} overlap with previous ${prevRop}`);\n                }\n            }\n        }\n\n        // WALK INSERTS\n        for (let i = 0; i < rewrites.length; i++) {\n            let op = rewrites[i];\n            if (op == null) {\n                continue;\n            }\n            if (!(op instanceof InsertBeforeOp)) {\n                continue;\n            }\n            let iop = op;\n            // combine current insert with prior if any at same index\n            let prevInserts = this.getKindOfOps(rewrites, InsertBeforeOp, i);\n            for (let prevIop of prevInserts) {\n                if (prevIop.index === iop.index) {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/JavaScript/src/antlr4/TokenStreamRewriter.js#L241-L277","documentation":"Thrown by IntervalSet.remove(int) when the set has been marked read-only with setReadonly(true). Read-only sets are shared across ATN instances and parsers; removing an element would silently change lexer/parser behavior everywhere the set is shared, so removal is rejected.","triggerScenarios":"Calling remove(el) on a set obtained from ATN transitions, statically cached sets, or any set after setReadonly(true) was invoked.","commonSituations":"Tools that filter character classes or token types out of ATN-derived interval sets; refactoring code that used to own its set but now receives a shared one from the runtime.","solutions":["Copy then remove: IntervalSet copy = new IntervalSet(shared); copy.remove(el);","Check isReadonly() before removal and route to the copy path.","Build a fresh set containing exactly the elements you want rather than subtracting from a shared one."],"exampleFix":"// before\nsharedSet.remove('\n'); // IllegalStateException\n\n// after\nIntervalSet filtered = new IntervalSet(sharedSet);\nfiltered.remove('\n');","handlingStrategy":"validation","validationCode":"IntervalSet target = set.isReadonly() ? new IntervalSet(set) : set;\ntarget.remove(el);","typeGuard":"boolean isMutable(IntervalSet s) { return !s.isReadonly(); }","tryCatchPattern":null,"preventionTips":["Never remove from ATN-owned or cached sets; copy first.","Build filtered sets from scratch instead of subtracting from shared ones.","Check isReadonly() in debug builds to catch bad mutation sites early."],"tags":["antlr","java","intervaset","immutable-state"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}