prestodb/presto · error · PinotException
PINOT_DECODE_ERROR
PINOT_DECODE_ERROR
Error message
Cannot decode double value from pinot %s
What it means
PinotUtils.parseDouble failed to convert a value returned by Pinot into a Presto double. The method special-cases NaN/infinity string tokens; any other unparseable value produces a NumberFormatException that is wrapped in this PINOT_DECODE_ERROR.
Source
Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/PinotUtils.java:95
return TimestampUtils.toMillisSinceEpoch(value);
}
}
}
public static Double parseDouble(String value)
{
try {
return Double.valueOf(value);
}
catch (NumberFormatException ne) {
switch (value) {
case PINOT_INFINITY:
case PINOT_POSITIVE_INFINITY:
return PRESTO_INFINITY;
case PINOT_NEGATIVE_INFINITY:
return PRESTO_NEGATIVE_INFINITY;
}
throw new PinotException(PINOT_DECODE_ERROR, Optional.empty(), "Cannot decode double value from pinot " + value, ne);
}
}
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Inspect the offending value in the message and clean/normalize the source column data in Pinot
- Cast or pre-format the column in SQL (e.g. date_trunc/CAST) so it parses as a number
- Extend the special-token handling in parseDouble for the unrecognized token (e.g. 'inf', '-Infinity')
- Check the timestamp format config (formatHint) for the column and fix the pattern
Example fix
// before
throw new PinotException(PINOT_DECODE_ERROR, Optional.empty(), "Cannot decode double value from pinot " + value, ne);
// after
if (value.equalsIgnoreCase("inf") || value.equalsIgnoreCase("+inf")) return PRESTO_INFINITY;
if (value.equalsIgnoreCase("-inf")) return PRESTO_NEGATIVE_INFINITY;
throw new PinotException(PINOT_DECODE_ERROR, Optional.empty(), "Cannot decode double value from pinot " + value, ne); Defensive patterns
Strategy: validation
Validate before calling
// validate the value parses before the connector sees it (source-side check)
try { Double.parseDouble(value); }
catch (NumberFormatException e) {
// normalize or reject at ingestion
value = normalizeSpecialTokens(value); // 'inf' -> 'Infinity' etc.
} Try / catch
try {
rows = query.execute();
} catch (PinotException e) {
if (PinotErrorCode.PINOT_DECODE_ERROR.toErrorCodeObject().equals(e.getErrorCode())) {
log.error("Unparseable numeric/timestamp value: %s", e.getMessage());
// rerun with the column cast to VARCHAR and decode client-side
executeWithCast(originalQuery, offendingColumn, "VARCHAR");
} else throw e;
} Prevention
- Enforce numeric/timestamp formats at Pinot ingestion time
- Provide correct formatHint for timestamp columns
- Check for NULL/garbage values in numeric columns with data quality queries
- Extend special-token handling when Pinot serializes NaN/Infinity differently
When it happens
Trigger: parseTimestamp (or another caller) passes a string that parseDouble cannot parse — e.g. non-numeric timestamp text, locale-formatted numbers, empty strings, or Pinot returning 'Infinity'/'NaN' variants not in the known token list.
Common situations: Timestamp columns stored as strings with non-numeric formats; Pinot returning special float tokens the connector doesn't recognize; data quality issues where NULL/garbage lands in a numeric column; connector/Pinot version drift in special-value serialization.
Related errors
- INVALID_CAST_ARGUMENT
- TimestampWithTimeZone overflow: %s ms
- Precision not supported
- nanos must be in range [0, 999_999_999]:
- Expected TimestampType but got {type.getClass().getName()}
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/15570c651baeb957.
Report an issue: GitHub.