prestodb/presto · error · OrcCorruptionException

Value is not null but decimal stream is not present

Error message

Value is not null but decimal stream is not present

What it means

DecimalBatchStreamReader.readBlock throws OrcCorruptionException when the present stream is null (meaning all values are treated as non-null) but the DECIMAL stream holding the numeric values is absent. A decimal column with non-null values must contain both its decimal data stream and a scale stream.

Source

Thrown at presto-orc/src/main/java/com/facebook/presto/orc/reader/DecimalBatchStreamReader.java:113

        if (!rowGroupOpen) {
            openRowGroup();
        }

        seekToOffset();

        if (decimalStream == null && scaleStream == null && presentStream != null) {
            presentStream.skip(nextBatchSize);
            Block nullValueBlock = RunLengthEncodedBlock.create(type, null, nextBatchSize);
            readOffset = 0;
            nextBatchSize = 0;
            return nullValueBlock;
        }

        BlockBuilder builder = type.createBlockBuilder(null, nextBatchSize);

        if (presentStream == null) {
            if (decimalStream == null) {
                throw new OrcCorruptionException(streamDescriptor.getOrcDataSourceId(), "Value is not null but decimal stream is not present");
            }
            if (scaleStream == null) {
                throw new OrcCorruptionException(streamDescriptor.getOrcDataSourceId(), "Value is not null but scale stream is not present");
            }

            for (int i = 0; i < nextBatchSize; i++) {
                long sourceScale = scaleStream.next();
                if (type.isShort()) {
                    long rescaledDecimal = Decimals.rescale(decimalStream.nextLong(), (int) sourceScale, type.getScale());
                    type.writeLong(builder, rescaledDecimal);
                }
                else {
                    Slice decimal = UnscaledDecimal128Arithmetic.unscaledDecimal();
                    Slice rescaledDecimal = UnscaledDecimal128Arithmetic.unscaledDecimal();

                    decimalStream.nextLongDecimal(decimal);
                    rescale(decimal, (int) (type.getScale() - sourceScale), rescaledDecimal);
                    type.writeSlice(builder, rescaledDecimal);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Regenerate the ORC file from source data with a reliable writer.
  2. Inspect stripe metadata with orc-tools to confirm the missing decimal stream.
  3. Verify the writer closes files completely; avoid reading in-progress files.
  4. Upgrade Presto/ORC reader and writer versions to rule out known stream-writing bugs.

Example fix

// before
SELECT dec_col FROM corrupt_table; // OrcCorruptionException
// after
-- rewrite the file, or guard:
try { readDecimal() } catch (OrcCorruptionException e) { fail/skip split }
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm decimal DATA and SECONDARY streams exist: orc-tools meta file.orc

Try / catch

try { block = streamReader.readBlock(); } catch (OrcCorruptionException e) { failQueryWithGuidance(e); }

Prevention

When it happens

Trigger: readBlock on a DECIMAL column where presentStream == null and decimalStream == null — i.e. the stripe has no decimal data stream though the reader assumes all rows are non-null.

Common situations: Truncated ORC files missing decimal streams; files written by buggy writers that skip empty-seeming streams; corrupt footers/stripe metadata mapping streams incorrectly.

Related errors


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