prestodb/presto · error · PrestoException

DECODER_CONVERSION_NOT_SUPPORTED

DECODER_CONVERSION_NOT_SUPPORTED

Error message

could not parse non-value node as '%s' for column '%s'

What it means

CustomDateTimeJsonFieldDecoder.getMillis() first asserts the JSON node is a value node (scalar). If the node is an object or array, formatter.parseMillis could never succeed, so DECODER_CONVERSION_NOT_SUPPORTED is thrown with this message. The JSON field expected to hold a datetime string is instead a nested structure.

Source

Thrown at presto-record-decoder/src/main/java/com/facebook/presto/decoder/json/CustomDateTimeJsonFieldDecoder.java:94

        return new CustomDateTimeJsonValueProvider(value, columnHandle, formatter);
    }

    public static class CustomDateTimeJsonValueProvider
            extends AbstractDateTimeJsonValueProvider
    {
        private final DateTimeFormatter formatter;

        public CustomDateTimeJsonValueProvider(JsonNode value, DecoderColumnHandle columnHandle, DateTimeFormatter formatter)
        {
            super(value, columnHandle);
            this.formatter = formatter;
        }

        @Override
        protected long getMillis()
        {
            if (!value.isValueNode()) {
                throw new PrestoException(
                        DECODER_CONVERSION_NOT_SUPPORTED,
                        format("could not parse non-value node as '%s' for column '%s'", columnHandle.getType(), columnHandle.getName()));
            }
            try {
                return formatter.parseMillis(value.asText());
            }
            catch (IllegalArgumentException e) {
                throw new PrestoException(
                        DECODER_CONVERSION_NOT_SUPPORTED,
                        format("could not parse value '%s' as '%s' for column '%s'", value.asText(), columnHandle.getType(), columnHandle.getName()));
            }
        }
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Fix the column mapping to point at the scalar leaf field holding the datetime string
  2. Flatten or pre-transform nested JSON upstream so the datetime is a plain string value
  3. Add defensive handling for records where the field is absent or nested
  4. Verify the current source payload shape (it may have changed from the original mapping)

Example fix

// before
{"name": "created", "mapping": "$.created"}  // {"created": {"date": "2024-01-01"}}
// after
{"name": "created", "mapping": "$.created.date"}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean isScalarAtPath(JsonNode root, String jsonPath) {
    JsonNode n = root.at(jsonPath.replace("$.", "/"));
    return n != null && n.isValueNode();
}

Type guard

boolean isDateTimeValueNode(JsonNode node) {
    return node != null && node.isValueNode() && node.isTextual();
}

Try / catch

try { row.getLong(columnName); }
catch (PrestoException e) {
    if (e.getErrorCode().getName().equals("DECODER_CONVERSION_NOT_SUPPORTED")
            && e.getMessage().contains("non-value node")) {
        log.warn("Field {} is nested/missing in payload", columnName); return null;
    }
    throw e;
}

Prevention

When it happens

Trigger: JSON mapping path ($ or format-hinted path) resolves to an object like {"date": "...", "tz": "..."} or an array instead of a scalar string; upstream API changed the field from a string to a nested object.

Common situations: Source API schema evolution wrapping datetime strings in objects; wrong JSON path in the column mapping pointing at a parent node; mixed-type fields where some records carry objects.

Related errors


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