antlr/antlr4 · error · InvalidOperationException
can't alter readonly IntervalSet
Error message
can't alter readonly IntervalSet
What it means
IntervalSet instances that the runtime publishes as shared constants are marked read-only; mutating them would corrupt every grammar and recognizer that shares the same set (e.g. the universal 'all tokens' or 'no tokens' sets). Clear() checks the read-only flag and throws InvalidOperationException instead of letting a shared constant be wiped.
Source
Thrown at runtime/CSharp/src/Misc/IntervalSet.cs:96
{
Antlr4.Runtime.Misc.IntervalSet s = new Antlr4.Runtime.Misc.IntervalSet();
s.Add(a);
return s;
}
/// <summary>Create a set with all ints within range [a..b] (inclusive)</summary>
public static Antlr4.Runtime.Misc.IntervalSet Of(int a, int b)
{
Antlr4.Runtime.Misc.IntervalSet s = new Antlr4.Runtime.Misc.IntervalSet();
s.Add(a, b);
return s;
}
public virtual void Clear()
{
if (@readonly)
{
throw new InvalidOperationException("can't alter readonly IntervalSet");
}
intervals.Clear();
}
/// <summary>Add a single element to the set.</summary>
/// <remarks>
/// Add a single element to the set. An isolated element is stored
/// as a range el..el.
/// </remarks>
public virtual void Add(int el)
{
if (@readonly)
{
throw new InvalidOperationException("can't alter readonly IntervalSet");
}
Add(el, el);
}
View on GitHub (pinned to 7d5770395b)
Solutions
- Never mutate sets you did not construct; create your own set and copy: var mine = new IntervalSet(theirs)
- If you need to modify a set, clone it first with the IntervalSet copy constructor, which yields a writable set
- Keep your mutable sets locally scoped and treat all runtime-returned IntervalSets as immutable
Example fix
// before IntervalSet expected = ctx.exception.GetExpectedTokens(); expected.Clear(); // may throw: read-only shared set // after IntervalSet expected = new IntervalSet(ctx.exception.GetExpectedTokens()); // writable copy expected.Clear();
Defensive patterns
Strategy: validation
Validate before calling
// Only clear sets you constructed; clone runtime-provided sets first IntervalSet writable = runtimeSet.IsReadOnly ? new IntervalSet(runtimeSet) : runtimeSet; writable.Clear();
Prevention
- Treat every IntervalSet returned by the runtime (expected tokens, transition labels) as immutable
- Use the IntervalSet copy constructor before mutating anything you didn't build
When it happens
Trigger: Calling Clear() on an IntervalSet obtained from runtime-owned state — typically error-recovery sets like recognizer.ErrorListener/DefaultErrorStrategy.GetErrorRecoverySet, ctx.exception.getExpectedTokens(), or transitions' label sets — rather than on a set you constructed yourself.
Common situations: Custom error strategies that want to reuse and clear an expected-tokens set; copying ATN structures and mutating the source's label sets; tests that mutate parser-time interval sets to simulate grammars.
Related errors
- The object is read only.
- can't alter readonly IntervalSet
- Invalid state number.
- Couldn't identify final state of the precedence rule prefix
- Could not deserialize ATN with version {0} (expected {1}).
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/88b95dd366752bd1.
Report an issue: GitHub.