{"record":{"id":"e87aa39723caa217","repo":"antlr/antlr4","slug":"the-object-is-read-only-e87aa3","errorCode":null,"errorMessage":"The object is read only.","messagePattern":"The object is read only\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"runtime/Python3/src/antlr4/atn/ATNDeserializationOptions.py","lineNumber":20,"sourceCode":"# Use of this file is governed by the BSD 3-clause license that\n# can be found in the LICENSE.txt file in the project root.\n\n# need a forward declaration\nATNDeserializationOptions = None\n\nclass ATNDeserializationOptions(object):\n    __slots__ = ('readonly', 'verifyATN', 'generateRuleBypassTransitions')\n\n    defaultOptions = None\n\n    def __init__(self, copyFrom:ATNDeserializationOptions = None):\n        self.readonly = False\n        self.verifyATN = True if copyFrom is None else copyFrom.verifyATN\n        self.generateRuleBypassTransitions = False if copyFrom is None else copyFrom.generateRuleBypassTransitions\n\n    def __setattr__(self, key, value):\n        if key!=\"readonly\" and self.readonly:\n            raise Exception(\"The object is read only.\")\n        super(type(self), self).__setattr__(key,value)\n\nATNDeserializationOptions.defaultOptions = ATNDeserializationOptions()\nATNDeserializationOptions.defaultOptions.readonly = True\n","sourceCodeStart":2,"sourceCodeEnd":25,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Python3/src/antlr4/atn/ATNDeserializationOptions.py#L2-L25","documentation":"ATNDeserializationOptions is a tiny read-only value object: after construction it can be mutated, but the module-level defaultOptions instance is frozen by setting readonly=True. Any attempt to set another attribute on a readonly instance (the custom __setattr__ blocks it) raises this Exception. In practice you hit it by mutating ATNDeserializationOptions.defaultOptions instead of making a copy.","triggerScenarios":"ATNDeserializationOptions.defaultOptions.verifyATN = False, or defaultOptions.generateRuleBypassTransitions = True — direct mutation of the frozen singleton.","commonSituations":"Trying to disable ATN verification or enable rule bypass transitions for the whole process by editing defaultOptions; code copied from the Java runtime where options are cloned.","solutions":["Copy first, then mutate, then pass explicitly: opts = ATNDeserializationOptions(ATNDeserializationOptions.defaultOptions); opts.verifyATN = False; ATNDeserializer(opts).deserialize(data).","Only touch the copy's flags (verifyATN, generateRuleBypassTransitions); never reassign attributes on defaultOptions itself."],"exampleFix":"# before\nATNDeserializationOptions.defaultOptions.verifyATN = False  # Exception: read only\n\n# after\nfrom antlr4.atn.ATNDeserializationOptions import ATNDeserializationOptions\nopts = ATNDeserializationOptions(ATNDeserializationOptions.defaultOptions)\nopts.verifyATN = False\ndeserializer = ATNDeserializer(opts)","handlingStrategy":"validation","validationCode":"def mutable_options(**flags):\n    opts = ATNDeserializationOptions(ATNDeserializationOptions.defaultOptions)\n    for k, v in flags.items():\n        setattr(opts, k, v)  # safe: copy is not readonly\n    return opts","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat defaultOptions as a frozen template; always copy-construct before changing flags","Never assign to attributes of module-level singletons in this runtime"],"tags":["antlr4","python","atn","deserialization-options","readonly"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}