antlr/antlr4 · error · UnsupportedOperationException

Serialized ATN data element[i] = v doesn't fit in 31 bits

Error message

Serialized ATN data element[i] = v doesn't fit in 31 bits

What it means

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.

Solutions

  1. Inspect the reported element index and value, then fix the producer that generated it.
  2. Reject values other than -1 and the supported non-negative range before encoding.
  3. Use ATNSerializer/SerializedJavaATN from one matching ANTLR version rather than hand-building the list.
  4. Check for corrupted or truncated integer lists before serialization.

Example fix

// before
IntegerList encoded = ATNDeserializer.encodeIntsWith16BitWords(data); // data contains 0x7FFFFFFF

// after
for (int i = 0; i < data.size(); i++) {
    int v = data.get(i);
    if (v != -1 && (v < 0 || v >= 0x7FFF_FFFF)) {
        throw new IllegalArgumentException("Bad serialized ATN value at " + i + ": " + v);
    }
}
IntegerList encoded = ATNDeserializer.encodeIntsWith16BitWords(data);
Defensive patterns

Strategy: validation

Validate before calling

static void validateSerializedIntegers(IntegerList data) {
    for (int i = 0; i < data.size(); i++) {
        int v = data.get(i);
        if (v != -1 && (v < 0 || v >= 0x7FFF_FFFF)) {
            throw new IllegalArgumentException("Element " + i + " cannot be encoded: " + v);
        }
    }
}

Try / catch

try {
    return ATNDeserializer.encodeIntsWith16BitWords(data);
} catch (UnsupportedOperationException e) {
    throw new IllegalArgumentException("Serialized ATN integer is out of range", e);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java:619

	 * 	This is only used (other than for testing) by {@link org.antlr.v4.codegen.model.SerializedJavaATN}
	 * 	to encode ints as char values for the java target, but it is convenient to combine it with the
	 * 	#decodeIntsEncodedAs16BitWords that follows as they are a pair (I did not want to introduce a new class
	 * 	into the runtime). Used only for Java Target.
	 */
	public static IntegerList encodeIntsWith16BitWords(IntegerList data) {
		IntegerList data16 = new IntegerList((int)(data.size()*1.5));
		for (int i = 0; i < data.size(); i++) {
			int v = data.get(i);
			if ( v==-1 ) { // use two max uint16 for -1
				data16.add(0xFFFF);
				data16.add(0xFFFF);
			}
			else if (v <= 0x7FFF) {
				data16.add(v);
			}
			else { // v > 0x7FFF
				if ( v>=0x7FFF_FFFF ) { // too big to fit in 15 bits + 16 bits? (+1 would be 8000_0000 which is bad encoding)
					throw new UnsupportedOperationException("Serialized ATN data element["+i+"] = "+v+" doesn't fit in 31 bits");
				}
				v = v & 0x7FFF_FFFF;					// strip high bit (sentinel) if set
				data16.add((v >> 16) | 0x8000);   // store high 15-bit word first and set high bit to say word follows
				data16.add((v & 0xFFFF)); 		// then store lower 16-bit word
			}
		}
		return data16;
	}

	public static int[] decodeIntsEncodedAs16BitWords(char[] data16) {
		return decodeIntsEncodedAs16BitWords(data16, false);
	}

	/** Convert a list of chars (16 uint) that represent a serialized and compressed list of ints for an ATN.
	 *  This method pairs with {@link #encodeIntsWith16BitWords(IntegerList)} above. Used only for Java Target.
	 */
	public static int[] decodeIntsEncodedAs16BitWords(char[] data16, boolean trimToSize) {
		// will be strictly smaller but we waste bit of space to avoid copying during initialization of parsers

View on GitHub (pinned to 7d5770395b)