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
- 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.
- 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.
- If bytes are garbage, treat the file as corrupt and regenerate it from source.
- 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
- Clamp/round decimals to declared precision+scale in ETL before writing.
- Match the producing system's precision settings to the ORC column type.
- Compare footer types with table schema during ingest validation.
- Use DECIMAL(38,x) columns when source precision is unbounded.
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
- Decimal does not fit long (invalid table schema?)
- NUMERIC_VALUE_OUT_OF_RANGE
- seconds field of timestamp exceeds maximum supported value,
- Timestamp exceeds maximum supported value, value: %s truncat
- Value is not null but decimal stream is not present
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/39ed884ea8b38367.
Report an issue: GitHub.