{"record":{"id":"fe67cd7fadfdcfc9","repo":"antlr/antlr4","slug":"serialized-atn-data-element-i-v-doesn-t-fit-in","errorCode":null,"errorMessage":"Serialized ATN data element[i] = v doesn't fit in 31 bits","messagePattern":"Serialized ATN data element\\[i\\] = v doesn't fit in 31 bits","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java","lineNumber":619,"sourceCode":"\t * \tThis is only used (other than for testing) by {@link org.antlr.v4.codegen.model.SerializedJavaATN}\n\t * \tto encode ints as char values for the java target, but it is convenient to combine it with the\n\t * \t#decodeIntsEncodedAs16BitWords that follows as they are a pair (I did not want to introduce a new class\n\t * \tinto the runtime). Used only for Java Target.\n\t */\n\tpublic static IntegerList encodeIntsWith16BitWords(IntegerList data) {\n\t\tIntegerList data16 = new IntegerList((int)(data.size()*1.5));\n\t\tfor (int i = 0; i < data.size(); i++) {\n\t\t\tint v = data.get(i);\n\t\t\tif ( v==-1 ) { // use two max uint16 for -1\n\t\t\t\tdata16.add(0xFFFF);\n\t\t\t\tdata16.add(0xFFFF);\n\t\t\t}\n\t\t\telse if (v <= 0x7FFF) {\n\t\t\t\tdata16.add(v);\n\t\t\t}\n\t\t\telse { // v > 0x7FFF\n\t\t\t\tif ( v>=0x7FFF_FFFF ) { // too big to fit in 15 bits + 16 bits? (+1 would be 8000_0000 which is bad encoding)\n\t\t\t\t\tthrow new UnsupportedOperationException(\"Serialized ATN data element[\"+i+\"] = \"+v+\" doesn't fit in 31 bits\");\n\t\t\t\t}\n\t\t\t\tv = v & 0x7FFF_FFFF;\t\t\t\t\t// strip high bit (sentinel) if set\n\t\t\t\tdata16.add((v >> 16) | 0x8000);   // store high 15-bit word first and set high bit to say word follows\n\t\t\t\tdata16.add((v & 0xFFFF)); \t\t// then store lower 16-bit word\n\t\t\t}\n\t\t}\n\t\treturn data16;\n\t}\n\n\tpublic static int[] decodeIntsEncodedAs16BitWords(char[] data16) {\n\t\treturn decodeIntsEncodedAs16BitWords(data16, false);\n\t}\n\n\t/** Convert a list of chars (16 uint) that represent a serialized and compressed list of ints for an ATN.\n\t *  This method pairs with {@link #encodeIntsWith16BitWords(IntegerList)} above. Used only for Java Target.\n\t */\n\tpublic static int[] decodeIntsEncodedAs16BitWords(char[] data16, boolean trimToSize) {\n\t\t// will be strictly smaller but we waste bit of space to avoid copying during initialization of parsers","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java#L601-L637","documentation":"encodeIntsWith16BitWords packs each serialized ATN integer into one or two unsigned 16-bit words. The special value -1 and values through 0x7FFF use one word; larger values use a sentinel high bit plus a second word. A value at or above 0x7FFF_FFFF cannot be encoded unambiguously in the available 31-bit representation and is rejected.","triggerScenarios":"Calling ATNDeserializer.encodeIntsWith16BitWords(IntegerList) when element i is 0x7FFF_FFFF or larger; feeding a custom/corrupted IntegerList into Java-target ATN generation; or a serializer bug producing an out-of-range state/rule/set/action value.","commonSituations":"Custom ATN serialization pipelines, generated-code targets that construct their own integer lists, and malformed ATN data. Normal grammar token/Unicode values are far below this limit.","solutions":["Inspect the reported element index and value, then fix the producer that generated it.","Reject values other than -1 and the supported non-negative range before encoding.","Use ATNSerializer/SerializedJavaATN from one matching ANTLR version rather than hand-building the list.","Check for corrupted or truncated integer lists before serialization."],"exampleFix":"// before\nIntegerList encoded = ATNDeserializer.encodeIntsWith16BitWords(data); // data contains 0x7FFFFFFF\n\n// after\nfor (int i = 0; i < data.size(); i++) {\n    int v = data.get(i);\n    if (v != -1 && (v < 0 || v >= 0x7FFF_FFFF)) {\n        throw new IllegalArgumentException(\"Bad serialized ATN value at \" + i + \": \" + v);\n    }\n}\nIntegerList encoded = ATNDeserializer.encodeIntsWith16BitWords(data);","handlingStrategy":"validation","validationCode":"static void validateSerializedIntegers(IntegerList data) {\n    for (int i = 0; i < data.size(); i++) {\n        int v = data.get(i);\n        if (v != -1 && (v < 0 || v >= 0x7FFF_FFFF)) {\n            throw new IllegalArgumentException(\"Element \" + i + \" cannot be encoded: \" + v);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return ATNDeserializer.encodeIntsWith16BitWords(data);\n} catch (UnsupportedOperationException e) {\n    throw new IllegalArgumentException(\"Serialized ATN integer is out of range\", e);\n}","preventionTips":["Validate integer lists before custom encoding.","Reject values outside -1 and the supported non-negative range.","Use matching ANTLR serializer code rather than building values manually."],"tags":["antlr","java","atn","serialization","encoding","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}