antlr/antlr4 · error · InvalidOperationException
The object is read only.
Error message
The object is read only.
What it means
ATNDeserializationOptions is a mutable options object that gets frozen (MakeReadOnly / IsReadOnly) after configuration. Every setter routes through ThrowIfReadOnly(), which throws InvalidOperationException('The object is read only.') if you mutate a frozen instance. Freezing prevents options from changing mid-deserialization.
Source
Thrown at runtime/CSharp/src/Atn/ATNDeserializationOptions.cs:112
public bool Optimize
{
get
{
return optimize;
}
set
{
bool optimize = value;
ThrowIfReadOnly();
this.optimize = optimize;
}
}
protected internal virtual void ThrowIfReadOnly()
{
if (IsReadOnly)
{
throw new InvalidOperationException("The object is read only.");
}
}
}
}
View on GitHub (pinned to 7d5770395b)
Solutions
- Create a fresh ATNDeserializationOptions instance per configuration (clone pattern), mutate, then let it be frozen
- Set all options before constructing/running the ATNDeserializer with them
Example fix
// before var opts = ATNDeserializationOptions.Default; opts.Optimize = true; // Default is read-only // after var opts = new ATNDeserializationOptions(); opts.Optimize = true; opts.MakeReadOnly();
Defensive patterns
Strategy: validation
Validate before calling
if (!options.IsReadOnly) { options.Optimize = true; } Type guard
static bool IsMutable(ATNDeserializationOptions o) => !o.IsReadOnly;
Try / catch
try { options.Optimize = true; } catch (InvalidOperationException) { /* frozen: create a fresh options instance instead */ } Prevention
- Never mutate Default/shared options instances; construct fresh ones
- Configure options fully before handing them to ATNDeserializer
When it happens
Trigger: Calling e.g. options.Optimize = true or options.VerifyATN = false after options.MakeReadOnly() was invoked — including when a default/shared instance (Default or the one inside ATNDeserializer) was already frozen.
Common situations: Reusing ATNDeserializer.DefaultOptions or a static options instance across deserializations and trying to tweak it per call; copying sample code that mutates options after passing them to a deserializer that freezes them.
Related errors
- Invalid state number.
- Couldn't identify final state of the precedence rule prefix
- Could not deserialize ATN with version {0} (expected {1}).
- Not yet implemented.
- The specified transition type is not valid.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/c7f672714dbf6a73.
Report an issue: GitHub.