{"record":{"id":"0272cdcf2aa6692a","repo":"prestodb/presto","slug":"function-implementation-error-0272cd","errorCode":"FUNCTION_IMPLEMENTATION_ERROR","errorMessage":"Should have received only one entry when scanning for number of rows in metrics table","messagePattern":"Should have received only one entry when scanning for number of rows in metrics table","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"presto-accumulo/src/main/java/com/facebook/presto/accumulo/index/IndexLookup.java","lineNumber":306,"sourceCode":"        double ratio = ((double) smallestCardinality / (double) numRows);\n        double threshold = getIndexSmallCardThreshold(session);\n        LOG.debug(\"Smallest cardinality is %d, num rows is %d, ratio is %2f with threshold of %f\", smallestCardinality, numRows, ratio, threshold);\n        return ratio > threshold;\n    }\n\n    private long getNumRowsInTable(String metricsTable, Authorizations auths)\n            throws TableNotFoundException\n    {\n        // Create scanner against the metrics table, pulling the special column and the rows column\n        Scanner scanner = connector.createScanner(metricsTable, auths);\n        scanner.setRange(METRICS_TABLE_ROWID_RANGE);\n        scanner.fetchColumn(METRICS_TABLE_ROWS_CF_AS_TEXT, CARDINALITY_CQ_AS_TEXT);\n\n        // Scan the entry and get the number of rows\n        long numRows = -1;\n        for (Entry<Key, Value> entry : scanner) {\n            if (numRows > 0) {\n                throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, \"Should have received only one entry when scanning for number of rows in metrics table\");\n            }\n            numRows = Long.parseLong(entry.getValue().toString());\n        }\n        scanner.close();\n\n        LOG.debug(\"Number of rows in table is %d\", numRows);\n        return numRows;\n    }\n\n    private List<Range> getIndexRanges(String indexTable, Multimap<AccumuloColumnConstraint, Range> constraintRanges, Collection<Range> rowIDRanges, Authorizations auths)\n    {\n        Set<Range> finalRanges = new HashSet<>();\n        // For each column/constraint pair we submit a task to scan the index ranges\n        List<Future<Set<Range>>> tasks = new ArrayList<>();\n        CompletionService<Set<Range>> executor = new ExecutorCompletionService<>(executorService);\n        for (Entry<AccumuloColumnConstraint, Collection<Range>> constraintEntry : constraintRanges.asMap().entrySet()) {\n            tasks.add(executor.submit(() -> {\n                // Create a batch scanner against the index table, setting the ranges","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-accumulo/src/main/java/com/facebook/presto/accumulo/index/IndexLookup.java#L288-L324","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before querying, scan the metrics table row and count CARDINALITY entries\nScanner s = conn.createScanner(metricsTable, auths);\ns.setRange(new Range(rowId));\ns.fetchColumnFamily(METRICS_TABLE_ROWS_CF_AS_TEXT);\nint n = 0;\nfor (Entry<Key, Value> e : s) { n++; }\nif (n > 1) {\n    throw new IllegalStateException(\"Duplicate CARDINALITY entries in metrics table; clean up before querying\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    long rows = indexLookup.numRows(schema, table, auths);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getName().equals(\"FUNCTION_IMPLEMENTATION_ERROR\")) {\n        // de-duplicate CARDINALITY entries in the metrics table, then retry\n    } else {\n        throw e;\n    }\n}","preventionTips":["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."],"tags":["accumulo","metrics-table","duplicate-data","index"],"backgroundTag":"duplicate-metrics-entry","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}