prestodb/presto · error

FUNCTION_IMPLEMENTATION_ERROR

FUNCTION_IMPLEMENTATION_ERROR

Error message

Should have received only one entry when scanning for number of rows in metrics table

What it means

IndexLookup.getNumRowsInTable scans the Accumulo metrics table for the single cardinality cell that records the table's row count and expects exactly one entry. If the scan yields more than one entry - meaning duplicate row-count rows exist in the metrics table - it throws FUNCTION_IMPLEMENTATION_ERROR because the count would be ambiguous.

Source

Thrown at presto-accumulo/src/main/java/com/facebook/presto/accumulo/index/IndexLookup.java:306

        double ratio = ((double) smallestCardinality / (double) numRows);
        double threshold = getIndexSmallCardThreshold(session);
        LOG.debug("Smallest cardinality is %d, num rows is %d, ratio is %2f with threshold of %f", smallestCardinality, numRows, ratio, threshold);
        return ratio > threshold;
    }

    private long getNumRowsInTable(String metricsTable, Authorizations auths)
            throws TableNotFoundException
    {
        // Create scanner against the metrics table, pulling the special column and the rows column
        Scanner scanner = connector.createScanner(metricsTable, auths);
        scanner.setRange(METRICS_TABLE_ROWID_RANGE);
        scanner.fetchColumn(METRICS_TABLE_ROWS_CF_AS_TEXT, CARDINALITY_CQ_AS_TEXT);

        // Scan the entry and get the number of rows
        long numRows = -1;
        for (Entry<Key, Value> entry : scanner) {
            if (numRows > 0) {
                throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, "Should have received only one entry when scanning for number of rows in metrics table");
            }
            numRows = Long.parseLong(entry.getValue().toString());
        }
        scanner.close();

        LOG.debug("Number of rows in table is %d", numRows);
        return numRows;
    }

    private List<Range> getIndexRanges(String indexTable, Multimap<AccumuloColumnConstraint, Range> constraintRanges, Collection<Range> rowIDRanges, Authorizations auths)
    {
        Set<Range> finalRanges = new HashSet<>();
        // For each column/constraint pair we submit a task to scan the index ranges
        List<Future<Set<Range>>> tasks = new ArrayList<>();
        CompletionService<Set<Range>> executor = new ExecutorCompletionService<>(executorService);
        for (Entry<AccumuloColumnConstraint, Collection<Range>> constraintEntry : constraintRanges.asMap().entrySet()) {
            tasks.add(executor.submit(() -> {
                // Create a batch scanner against the index table, setting the ranges

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Inspect the metrics table row (accumulo shell scan for this table's row-ID) and delete duplicate CARDINALITY entries, keeping one correct value.
  2. Drop and recreate the table so its metrics entries are rebuilt cleanly.
  3. Check for a prior failed CREATE/DROP that left stale metrics rows and clean up the orphaned Accumulo tables.
  4. If reproducible on a stock connector, report a bug with the duplicate-entry details.
Defensive patterns

Strategy: try-catch

Validate before calling

// before querying, scan the metrics table row and count CARDINALITY entries
Scanner s = conn.createScanner(metricsTable, auths);
s.setRange(new Range(rowId));
s.fetchColumnFamily(METRICS_TABLE_ROWS_CF_AS_TEXT);
int n = 0;
for (Entry<Key, Value> e : s) { n++; }
if (n > 1) {
    throw new IllegalStateException("Duplicate CARDINALITY entries in metrics table; clean up before querying");
}

Try / catch

try {
    long rows = indexLookup.numRows(schema, table, auths);
} catch (PrestoException e) {
    if (e.getErrorCode().getName().equals("FUNCTION_IMPLEMENTATION_ERROR")) {
        // de-duplicate CARDINALITY entries in the metrics table, then retry
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Multiple metrics-table rows exist with the same row-ID/column-family/CARDINALITY qualifier - typically caused by a failed or re-run table creation that inserted the row-count entry twice, or duplicate/manual writes to the metrics table.

Common situations: Recreating a table with the same name after a failed drop; metrics table left in a stale state after a crash; duplicate entries accumulated over time from a connector bug; hand-edited metrics table.

Related errors


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