prestodb/presto · error · JsonCastException

INVALID_CAST_ARGUMENT

INVALID_CAST_ARGUMENT

Error message

Expected a json object, but got %s

What it means

Cast error from the JSON-to-map cast: the JSON text being cast was parsed successfully but its top-level token is not an object (e.g. it is an array or a scalar). A map can only be built from a JSON object whose keys become map keys; the %s reports the actual JSON token found.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/scalar/JsonToMapCast.java:99

        BlockBuilderAppender valueAppender = createBlockBuilderAppender(mapType.getValueType());
        MethodHandle methodHandle = METHOD_HANDLE.bindTo(mapType).bindTo(keyAppender).bindTo(valueAppender);
        return new BuiltInScalarFunctionImplementation(
                true,
                ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL)),
                methodHandle);
    }

    @UsedByGeneratedCode
    public static Block toMap(MapType mapType, BlockBuilderAppender keyAppender, BlockBuilderAppender valueAppender, SqlFunctionProperties properties, Slice json)
    {
        try (JsonParser jsonParser = createJsonParser(JSON_FACTORY, json)) {
            jsonParser.nextToken();
            if (jsonParser.getCurrentToken() == JsonToken.VALUE_NULL) {
                return null;
            }

            if (jsonParser.getCurrentToken() != START_OBJECT) {
                throw new JsonCastException(format("Expected a json object, but got %s", jsonParser.getText()));
            }
            BlockBuilder mapBlockBuilder = mapType.createBlockBuilder(null, 1);
            BlockBuilder singleMapBlockBuilder = mapBlockBuilder.beginBlockEntry();
            HashTable hashTable = new HashTable(mapType.getKeyType(), singleMapBlockBuilder);
            int position = 0;
            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                keyAppender.append(jsonParser, singleMapBlockBuilder, properties);
                jsonParser.nextToken();
                valueAppender.append(jsonParser, singleMapBlockBuilder, properties);

                // Duplicate key detection is required even if the JSON is valid.
                // For example: CAST(JSON '{"1": 1, "01": 2}' AS MAP<INTEGER, INTEGER>).
                if (!hashTable.addIfAbsent(position)) {
                    throw new JsonCastException("Duplicate keys are not allowed");
                }
                position += 2;
            }
            if (jsonParser.nextToken() != null) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the JSON value is an object like {"k": v} before casting to map
  2. Use json_parse plus cast(json AS map(...)) only on object-shaped JSON
  3. Transform arrays with transform() into maps first if the data is array-shaped
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/scalar/JsonToMapCast.java:99 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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