prestodb/presto · error · JsonCastException
INVALID_CAST_ARGUMENT
INVALID_CAST_ARGUMENT
Error message
Unexpected token when cast to %s: %s
What it means
currentTokenAsVarchar converts the current Jackson parser token to a Presto VARCHAR during JSON-to-SQL casting. Only VALUE_STRING, VALUE_NUMBER, VALUE_TRUE and VALUE_FALSE are convertible; any other token (null, START_OBJECT, START_ARRAY, FIELD_NAME, NOT_AVAILABLE, embedded objects) throws JsonCastException (INVALID_CAST_ARGUMENT) naming VARCHAR and the offending token text.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/util/JsonUtil.java:702
switch (parser.currentToken()) {
case VALUE_NULL:
return null;
case VALUE_STRING:
case FIELD_NAME:
return Slices.utf8Slice(parser.getText());
case VALUE_NUMBER_FLOAT:
// Avoidance of loss of precision does not seem to be possible here because of Jackson implementation.
return DoubleOperators.castToVarchar(parser.getDoubleValue());
case VALUE_NUMBER_INT:
// An alternative is calling getLongValue and then BigintOperators.castToVarchar.
// It doesn't work as well because it can result in overflow and underflow exceptions for large integral numbers.
return Slices.utf8Slice(parser.getText());
case VALUE_TRUE:
return BooleanOperators.castToVarchar(true);
case VALUE_FALSE:
return BooleanOperators.castToVarchar(false);
default:
throw new JsonCastException(format("Unexpected token when cast to %s: %s", StandardTypes.VARCHAR, parser.getText()));
}
}
public static Long currentTokenAsBigint(JsonParser parser)
throws IOException
{
switch (parser.currentToken()) {
case VALUE_NULL:
return null;
case VALUE_STRING:
case FIELD_NAME:
return VarcharOperators.castToBigint(Slices.utf8Slice(parser.getText()));
case VALUE_NUMBER_FLOAT:
return DoubleOperators.castToLong(parser.getDoubleValue());
case VALUE_NUMBER_INT:
return parser.getLongValue();
case VALUE_TRUE:
return BooleanOperators.castToBigint(true);View on GitHub (pinned to 55bb57d202)
Solutions
- Check the JSON value is a scalar (string, number, or boolean) before casting to VARCHAR; handle nulls with json_typeof or JSON_QUERY wrappers.
- Coerce objects/arrays with json_format(CAST(col AS JSON)) instead of direct CAST to VARCHAR.
- Fix the upstream producer so the field is always a JSON string, or use TRY_CAST to get NULL instead of a query failure.
Example fix
// before SELECT CAST(json_extract(j, '$.details') AS VARCHAR) FROM t; -- fails when details is an object // after SELECT TRY_CAST(json_extract(j, '$.details') AS VARCHAR) FROM t; -- NULL instead of error, or guard with json_typeof
Defensive patterns
Strategy: try-catch
Validate before calling
SELECT json_typeof(json_extract(j, '$.path')) FROM t; -- must be 'string', 'number', or 'boolean' before CAST to VARCHAR
Type guard
boolean isVarcharCastable(String jsonValue) {
String t = jsonTypeOf(jsonValue); // e.g. via json_typeof
return "string".equals(t) || "number".equals(t) || "boolean".equals(t);
} Try / catch
try {
v = castJsonToVarchar(j);
} catch (PrestoException e) {
if (e.getErrorCode().getName().equals("INVALID_CAST_ARGUMENT") && e.getMessage().contains("varchar")) {
v = jsonFormat(j); // serialize objects/arrays instead
} else { throw e; }
} Prevention
- Check json_typeof before casting extracted JSON values.
- Use json_format for objects/arrays instead of direct VARCHAR casts.
- Prefer TRY_CAST for untrusted semi-structured JSON.
When it happens
Trigger: Casting a JSON value that is an object, array, or null to VARCHAR — e.g. CAST(JSON 'null' AS VARCHAR), CAST(JSON '{"a":1}' AS VARCHAR), or a JSON path/unnest landing on a non-scalar token.
Common situations: Ingesting semi-structured JSON where a field expected to be a string is sometimes an object/array/null; schema drift between producer and consumer; using json_extract with an implicit cast when the path hits a container.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/499056875663e620.
Report an issue: GitHub.