{"record":{"id":"ae22851ef19382a9","repo":"antlr/antlr4","slug":"the-object-is-read-only","errorCode":null,"errorMessage":"The object is read only.","messagePattern":"The object is read only\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializationOptions.java","lineNumber":67,"sourceCode":"\t}\n\n\tpublic final void setVerifyATN(boolean verifyATN) {\n\t\tthrowIfReadOnly();\n\t\tthis.verifyATN = verifyATN;\n\t}\n\n\tpublic final boolean isGenerateRuleBypassTransitions() {\n\t\treturn generateRuleBypassTransitions;\n\t}\n\n\tpublic final void setGenerateRuleBypassTransitions(boolean generateRuleBypassTransitions) {\n\t\tthrowIfReadOnly();\n\t\tthis.generateRuleBypassTransitions = generateRuleBypassTransitions;\n\t}\n\n\tprotected void throwIfReadOnly() {\n\t\tif (isReadOnly()) {\n\t\t\tthrow new IllegalStateException(\"The object is read only.\");\n\t\t}\n\t}\n}\n","sourceCodeStart":49,"sourceCodeEnd":71,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializationOptions.java#L49-L71","documentation":"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.","triggerScenarios":"Calling ATNDeserializationOptions.getDefaultOptions().setVerifyATN(false); calling any setter after explicitly invoking makeReadOnly(); or caching one options object, sealing it, and later reconfiguring it.","commonSituations":"Trying to tune the global default deserialization behavior, sharing an options singleton across setup code, and custom ATN deserializers.","solutions":["Create new ATNDeserializationOptions() for mutable settings.","Use the copy constructor when deriving from existing options; it copies settings but not readOnly.","Call makeReadOnly() only after all setters have run.","Never mutate getDefaultOptions(); pass it to ATNDeserializer unchanged."],"exampleFix":"// before\nATNDeserializationOptions options = ATNDeserializationOptions.getDefaultOptions();\noptions.setVerifyATN(false); // default instance is readonly\n\n// after\nATNDeserializationOptions options = new ATNDeserializationOptions();\noptions.setVerifyATN(false);\nATN atn = new ATNDeserializer(options).deserialize(serializedAtn);","handlingStrategy":"validation","validationCode":"static ATNDeserializationOptions mutableCopy(ATNDeserializationOptions source) {\n    ATNDeserializationOptions copy = new ATNDeserializationOptions(source);\n    if (copy.isReadOnly()) {\n        throw new IllegalStateException(\"Copy unexpectedly readonly\");\n    }\n    return copy;\n}","typeGuard":null,"tryCatchPattern":"try {\n    options.setVerifyATN(false);\n} catch (IllegalStateException e) {\n    options = new ATNDeserializationOptions();\n    options.setVerifyATN(false);\n}","preventionTips":["Never mutate getDefaultOptions().","Create options locally per deserializer configuration.","Seal options only after configuration is complete."],"tags":["antlr","java","atn","deserialization","options","readonly"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}