prestodb/presto · error · OrcCorruptionException

Decimal exceeds 128 bits

Error message

Decimal exceeds 128 bits

What it means

Thrown by DecimalInputStream.nextLongDecimal when a varint-encoded decimal requires more than 128 bits of significand: at offset==126 the code checks whether the current byte's high bit signals more bytes or whether its low 7 bits exceed 3, either of which would overflow a 128-bit (16-byte) decimal. ORC DECIMAL(38,x) values must fit in 128 bits; larger values mean the file's data does not match the declared schema.

Source

Thrown at presto-orc/src/main/java/com/facebook/presto/orc/stream/DecimalInputStream.java:61

    @Override
    public void seekToCheckpoint(DecimalStreamCheckpoint checkpoint)
            throws IOException
    {
        input.seekToCheckpoint(checkpoint.getInputStreamCheckpoint());
    }

    public void nextLongDecimal(Slice result)
            throws IOException
    {
        long b;
        long offset = 0;
        long low = 0;
        long high = 0;
        do {
            b = input.read();
            if (offset == 126 && ((b & 0x80) > 0 || (b & 0x7f) > 3)) {
                throw new OrcCorruptionException(input.getOrcDataSourceId(), "Decimal exceeds 128 bits");
            }

            if (offset < 63) {
                low |= (b & 0x7f) << offset;
            }
            else if (offset == 63) {
                low |= (b & 0x01) << offset;
                high |= (b & 0x7f) >>> 1;
            }
            else {
                high |= (b & 0x7f) << (offset - 64);
            }
            offset += 7;
        }
        while ((b & 0x80) > 0);

        boolean negative = (low & 0x01) == 1;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Compare the ORC footer type (orc-dump) with the table schema; widen the Presto table column (e.g. up to DECIMAL(38,x)) or fix the writer to emit values within 128 bits.
  2. Locate and rewrite offending rows: filter source data by the column to find values exceeding DECIMAL(38,x) range and clamp/round them before rewriting.
  3. If bytes are garbage, treat the file as corrupt and regenerate it from source.
  4. Ensure the producing engine's decimal precision matches ORC's 128-bit limit (e.g. avoid writing 40-digit decimals into a 38-digit column).

Example fix

// before: writing oversized decimal
BigDecimal v = new BigDecimal("123456789012345678901234567890123456789012345"); // 45 digits
// after: clamp to the declared precision before writing
BigDecimal v2 = v.setScale(scale, RoundingMode.HALF_UP)
    .min(new BigDecimal("9.9999999999999999999999999999999999999E+37"));
Defensive patterns

Strategy: validation

Validate before calling

// on the write side, guarantee values fit DECIMAL(38,x)
BigDecimal max = new BigDecimal("1").movePointLeft(scale)
    .multiply(new BigDecimal("9").repeat(38));
if (value.abs().compareTo(max) > 0) {
    throw new IllegalArgumentException("value exceeds 128-bit decimal: " + value);
}

Try / catch

try {
    return decimalStream.nextLongDecimal(values);
} catch (OrcCorruptionException e) {
    if (e.getMessage().contains("exceeds 128 bits")) {
        throw new SchemaMismatchException("data wider than declared DECIMAL(38,x)", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Reading a LONG_DECIMAL column via nextLongDecimal where the encoded varint has a byte at position 126 with the continuation bit set, or with a 7-bit payload > 3 (i.e. the value needs > 128 bits).

Common situations: A table schema defined with DECIMAL(38,p) but data written by a system allowing wider precision; corrupt/garbage bytes interpreted as an over-long varint; writers producing decimals incompatible with the ORC type declared in the footer.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/39ed884ea8b38367. Report an issue: GitHub.