antlr/antlr4 · error · Error
insert op ${iop} within boundaries of previous ${rop}
Error message
insert op ${iop} within boundaries of previous ${rop} What it means
Thrown by IntervalSet.setReadonly(false) when the set is currently read-only. Read-only status is deliberately one-way in the ANTLR runtime: it protects sets shared between threads and ATN caches, and allowing an un-flag would open a race where one consumer mutates while others read. Only transitioning false→true is legal.
Source
Thrown at runtime/JavaScript/src/antlr4/TokenStreamRewriter.js:300
else if (prevIop instanceof InsertBeforeOp) { // combine objects
// convert to strings...we're in process of toString'ing
// whole token buffer so no lazy eval issue with any templates
iop.text = this.catOpText(iop.text, prevIop.text);
// delete redundant prior insert
rewrites[prevIop.instructionIndex] = undefined;
}
}
}
// look for replaces where iop.index is in range; error
let prevReplaces = this.getKindOfOps(rewrites, ReplaceOp, i);
for (let rop of prevReplaces) {
if (iop.index === rop.index) {
rop.text = this.catOpText(iop.text, rop.text);
rewrites[i] = undefined; // delete current insert
continue;
}
if (iop.index >= rop.index && iop.index <= rop.lastIndex) {
throw new Error(`insert op ${iop} within boundaries of previous ${rop}`);
}
}
}
/** @type {Map<number, RewriteOperation>} */
let m = new Map();
for (let op of rewrites) {
if (op == null) {
// ignore deleted ops
continue;
}
if (m.get(op.index) != null) {
throw new Error("should only be one op per index");
}
m.set(op.index, op);
}
return m;
}View on GitHub (pinned to 7d5770395b)
Solutions
- Never un-flag: clone the set (new IntervalSet(set)) and mutate the clone.
- Design construction so setReadonly(true) is the last step, after all mutation is done.
- If you need freeze/thaw semantics, implement them in your own wrapper that swaps between mutable copies.
Example fix
// before set.setReadonly(true); // ... later set.setReadonly(false); // IllegalStateException // after set.setReadonly(true); // ... later, work on a copy IntervalSet mutable = new IntervalSet(set);
Defensive patterns
Strategy: validation
Validate before calling
// setReadonly is one-way; to 'unlock', copy IntervalSet fresh = new IntervalSet(readonlySet); // fresh is mutable fresh.add(newInterval);
Prevention
- Model readonly as one-way in your own code too.
- Freeze sets only at the end of their construction pipeline.
- Replace 'thaw' logic with clone-and-mutate.
When it happens
Trigger: Calling setReadonly(false) on a set that already had setReadonly(true) applied, e.g. an attempt to 'unlock' a cached or ATN-owned set for modification.
Common situations: Code that wants to temporarily freeze and then thaw a set; sets acquired from the runtime's shared state that the application tries to make mutable again.
Related errors
- replace op boundaries of ${rop} overlap with previous ${prev
- should only be one op per index
- index cannot be negative
- missing interface implementation
- Fatal error occured while evaluating the names of the gramma
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/557ab8700db272eb.
Report an issue: GitHub.