antlr/antlr4 · error · IllegalStateException

The object is read only.

Error message

The object is read only.

What it means

ATNDeserializationOptions becomes immutable after makeReadOnly(), and the static defaultOptions instance is created read-only. Any setter such as setVerifyATN or setGenerateRuleBypassTransitions throws IllegalStateException on that object. Mutable options must be a separately constructed instance.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializationOptions.java:67

	}

	public final void setVerifyATN(boolean verifyATN) {
		throwIfReadOnly();
		this.verifyATN = verifyATN;
	}

	public final boolean isGenerateRuleBypassTransitions() {
		return generateRuleBypassTransitions;
	}

	public final void setGenerateRuleBypassTransitions(boolean generateRuleBypassTransitions) {
		throwIfReadOnly();
		this.generateRuleBypassTransitions = generateRuleBypassTransitions;
	}

	protected void throwIfReadOnly() {
		if (isReadOnly()) {
			throw new IllegalStateException("The object is read only.");
		}
	}
}

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Create new ATNDeserializationOptions() for mutable settings.
  2. Use the copy constructor when deriving from existing options; it copies settings but not readOnly.
  3. Call makeReadOnly() only after all setters have run.
  4. Never mutate getDefaultOptions(); pass it to ATNDeserializer unchanged.

Example fix

// before
ATNDeserializationOptions options = ATNDeserializationOptions.getDefaultOptions();
options.setVerifyATN(false); // default instance is readonly

// after
ATNDeserializationOptions options = new ATNDeserializationOptions();
options.setVerifyATN(false);
ATN atn = new ATNDeserializer(options).deserialize(serializedAtn);
Defensive patterns

Strategy: validation

Validate before calling

static ATNDeserializationOptions mutableCopy(ATNDeserializationOptions source) {
    ATNDeserializationOptions copy = new ATNDeserializationOptions(source);
    if (copy.isReadOnly()) {
        throw new IllegalStateException("Copy unexpectedly readonly");
    }
    return copy;
}

Try / catch

try {
    options.setVerifyATN(false);
} catch (IllegalStateException e) {
    options = new ATNDeserializationOptions();
    options.setVerifyATN(false);
}

Prevention

When it happens

Trigger: Calling ATNDeserializationOptions.getDefaultOptions().setVerifyATN(false); calling any setter after explicitly invoking makeReadOnly(); or caching one options object, sealing it, and later reconfiguring it.

Common situations: Trying to tune the global default deserialization behavior, sharing an options singleton across setup code, and custom ATN deserializers.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/ae22851ef19382a9. Report an issue: GitHub.