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 rangesView on GitHub (pinned to 55bb57d202)
Solutions
- Inspect the metrics table row (accumulo shell scan for this table's row-ID) and delete duplicate CARDINALITY entries, keeping one correct value.
- Drop and recreate the table so its metrics entries are rebuilt cleanly.
- Check for a prior failed CREATE/DROP that left stale metrics rows and clean up the orphaned Accumulo tables.
- 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
- Ensure CREATE TABLE failures are fully cleaned up (drop both data and metrics tables) before recreating the same-named table.
- Periodically audit the metrics table for duplicate CARDINALITY entries.
- Never manually write rows into the Accumulo metrics table.
- Report reproducible duplicates to the connector maintainers.
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.