prestodb/presto · error · RedisProviderSerdeException

Error encoding historicalPlanStatistics value

Error message

Error encoding historicalPlanStatistics value

What it means

HistoricalStatisticsSerde.encodeValue serializes HistoricalPlanStatistics with a Thrift binary protocol writer into a DynamicSliceOutput. If ThriftProtocolUtils.write throws ThriftProtocolException (malformed object, incompatible schema, null required fields), the method wraps it in RedisProviderSerdeException with this message.

Source

Thrown at redis-hbo-provider/src/main/java/com/facebook/presto/statistic/HistoricalStatisticsSerde.java:66

    }

    @Override
    public ByteBuffer encodeKey(String key)
    {
        return ByteBuffer.wrap(key.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public ByteBuffer encodeValue(HistoricalPlanStatistics historicalPlanStatistics)
    {
        ThriftCodec<HistoricalPlanStatistics> writeCodec = thriftCodecManager.getCodec(HistoricalPlanStatistics.class);
        SliceOutput dynamicSliceOutput = new DynamicSliceOutput(ESTIMATED_BUFFER_SIZE_BYTES);
        try {
            ThriftProtocolUtils.write(historicalPlanStatistics, writeCodec, Protocol.BINARY, dynamicSliceOutput);
            return ByteBuffer.wrap(dynamicSliceOutput.slice().getBytes());
        }
        catch (ThriftProtocolException e) {
            throw new RedisProviderSerdeException("Error encoding historicalPlanStatistics value", e);
        }
    }

    @Override
    public HistoricalPlanStatistics decodeValue(ByteBuffer byteBuffer)
    {
        ThriftCodec<HistoricalPlanStatistics> readCodec = thriftCodecManager.getCodec(HistoricalPlanStatistics.class);
        try {
            return ThriftProtocolUtils.read(readCodec, Protocol.BINARY, Slices.wrappedBuffer(byteBuffer).getInput());
        }
        catch (ThriftProtocolException e) {
            throw new RedisProviderSerdeException("Error decoding historicalPlanStatistics value", e);
        }
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Check the ThriftProtocolException cause for the specific field/schema mismatch and align the HistoricalPlanStatistics schema with the writeCodec
  2. Regenerate/update Thrift codec classes after a schema version change
  3. Validate the HistoricalPlanStatistics object (required fields present) before encoding
  4. Catch and log at the call site (encodedValue) to avoid losing the whole statistics pipeline

Example fix

// before
HistoricalPlanStatistics stats = new HistoricalPlanStatistics(); // required fields unset
serde.encodeValue(stats);
// after
if (stats == null || stats.getPlans() == null) {
    throw new IllegalArgumentException("HistoricalPlanStatistics missing required fields");
}
serde.encodeValue(stats);
Defensive patterns

Strategy: try-catch

Validate before calling

if (stats == null) throw new IllegalArgumentException("historicalPlanStatistics must not be null");

Try / catch

try {
    ByteBuffer encoded = serde.encodeValue(stats);
} catch (RedisProviderSerdeException e) {
    log.error("Failed to encode HBO stats", e.getCause());
    // skip caching this entry rather than failing the query
}

Prevention

When it happens

Trigger: Calling encodeValue with a HistoricalPlanStatistics whose schema is incompatible with the configured writeCodec (schema evolution mismatch), or with fields the Thrift writer cannot serialize.

Common situations: HBO statistics schema changed between Presto versions so old objects no longer match the write codec; a partially constructed HistoricalPlanStatistics (missing required fields) is passed in; Thrift codec misconfiguration.

Related errors


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