prestodb/presto · error · PrestoException

ELASTICSEARCH_TYPE_MISMATCH

ELASTICSEARCH_TYPE_MISMATCH

Error message

Expected a numeric value for field '%s' of type INTEGER: %s [%s]

What it means

The Elasticsearch connector's IntegerDecoder found a document field value that is not a java.lang.Number when decoding it into a Presto INTEGER column. The connector only coerces actual numbers; any other JSON type (string, boolean, object, array) is rejected rather than silently cast. This keeps Presto's type system from receiving garbage data from loosely-typed Elasticsearch documents.

Source

Thrown at presto-elasticsearch/src/main/java/com/facebook/presto/elasticsearch/decoders/IntegerDecoder.java:49

    private final String path;

    public IntegerDecoder(String path)
    {
        this.path = requireNonNull(path, "path is null");
    }

    @Override
    public void decode(Hit hit, Supplier<Object> getter, BlockBuilder output)
    {
        Object value = getter.get();
        if (value == null) {
            output.appendNull();
        }
        else if (value instanceof Number) {
            INTEGER.writeLong(output, toIntExact(((Number) value).longValue()));
        }
        else {
            throw new PrestoException(ELASTICSEARCH_TYPE_MISMATCH, format("Expected a numeric value for field '%s' of type INTEGER: %s [%s]", path, value, value.getClass().getSimpleName()));
        }
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Fix the document data so the field holds a JSON number, e.g. reindex with "age": 42 instead of "age": "42".
  2. Change the Presto table column mapping to VARCHAR/JSON to match the actual stored type, and cast in SQL.
  3. Add or fix the Elasticsearch dynamic mapping / Presto field definition so the field is mapped as integer before ingesting.

Example fix

// before (document)
{"age": "42"}
// after
{"age": 42}
Defensive patterns

Strategy: validation

Validate before calling

SELECT t.age FROM idx t WHERE t.age IS NOT NULL AND TYPEOF(t.age) <> 'integer' LIMIT 1;
-- or at ingest: assert(typeof doc.age === 'number')

Type guard

function isIntegerValue(v) { return typeof v === 'number' && Number.isFinite(v) && Number.isInteger(v); }

Try / catch

try { SELECT age FROM "idx" } catch (PrestoException e) { if ("ELASTICSEARCH_TYPE_MISMATCH".equals(e.getErrorCode().getName())) { /* re-map column or clean data */ } else { throw e; } }

Prevention

When it happens

Trigger: decode() is called with a hit field whose mapped Presto type is INTEGER but whose stored JSON value is a non-number, e.g. {"age": "42"} or {"age": true} while the connector metadata declares the column as INTEGER.

Common situations: Elasticsearch dynamic mapping created the field as text/keyword from early string documents, then the Presto external table was declared INTEGER; schema drift between documents in the same index (some documents use strings, others numbers); accidental JSON quoting in the indexing pipeline.

Related errors


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