{"record":{"id":"212b672293a811fc","repo":"prestodb/presto","slug":"unexpected-accumulo-error-212b67","errorCode":"UNEXPECTED_ACCUMULO_ERROR","errorMessage":"Exception when getting index ranges","messagePattern":"Exception when getting index ranges","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"presto-accumulo/src/main/java/com/facebook/presto/accumulo/index/IndexLookup.java","lineNumber":365,"sourceCode":"        }\n        tasks.forEach(future ->\n        {\n            try {\n                // If finalRanges is null, we have not yet added any column ranges\n                if (finalRanges.isEmpty()) {\n                    finalRanges.addAll(future.get());\n                }\n                else {\n                    // Retain only the row IDs for this column that have already been added\n                    // This is your set intersection operation!\n                    finalRanges.retainAll(future.get());\n                }\n            }\n            catch (ExecutionException | InterruptedException e) {\n                if (e instanceof InterruptedException) {\n                    Thread.currentThread().interrupt();\n                }\n                throw new PrestoException(UNEXPECTED_ACCUMULO_ERROR, \"Exception when getting index ranges\", e.getCause());\n            }\n        });\n        return ImmutableList.copyOf(finalRanges);\n    }\n\n    private static void binRanges(int numRangesPerBin, List<Range> splitRanges, List<TabletSplitMetadata> prestoSplits)\n    {\n        checkArgument(numRangesPerBin > 0, \"number of ranges per bin must be greater than zero\");\n        int toAdd = splitRanges.size();\n        int fromIndex = 0;\n        int toIndex = Math.min(toAdd, numRangesPerBin);\n        do {\n            // Add the sublist of range handles\n            // Use an empty location because we are binning multiple Ranges spread across many tablet servers\n            prestoSplits.add(new TabletSplitMetadata(Optional.empty(), splitRanges.subList(fromIndex, toIndex)));\n            toAdd -= toIndex - fromIndex;\n            fromIndex = toIndex;\n            toIndex += Math.min(toAdd, numRangesPerBin);","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-accumulo/src/main/java/com/facebook/presto/accumulo/index/IndexLookup.java#L347-L383","documentation":"PrestoException with code UNEXPECTED_ACCUMULO_ERROR thrown from getIndexRanges when the future gathering Accumulo index ranges fails with an ExecutionException or InterruptedException. The real failure (scan error, table offline, interruption) is attached as the cause. The interrupt flag is restored before throwing so cancellation is not swallowed.","triggerScenarios":"Calling IndexLookup.getIndexRanges (via indexRanges or getRangesWithMetrics) when the underlying Accumulo range-lookup future fails: tablet server unreachable, scan timeout, index table deleted/offlined mid-query, or the query thread being cancelled/interrupted.","commonSituations":"Accumulo cluster degraded or restarted during a query; wrong zookeeper/instance config making scans hang then fail; user killing the Presto query causing Future cancellation; network partition between Presto workers and Accumulo tservers.","solutions":["Inspect the cause chain (e.getCause()) for the real Accumulo exception and fix the underlying scan failure","Verify Accumulo connectivity (zookeepers, instance name) and that the index table exists and is online in the Accumulo shell","Retry the query; transient tablet-server or network failures often resolve","If the cause is InterruptedException, check what cancelled the query (timeout, user kill, resource limits) and re-run"],"exampleFix":"// before\nList<Range> ranges = indexLookup.getIndexRanges(constraints);\n// after\ntry {\n    List<Range> ranges = indexLookup.getIndexRanges(constraints);\n} catch (PrestoException e) {\n    log.warn(\"index range lookup failed\", e.getCause()); // inspect the real cause\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// verify Accumulo reachability and index table presence before querying\nif (!accumuloClient.tableOperations().exists(indexTable)) throw new IllegalStateException(\"index table missing\");\nif (!accumuloClient.tableOperations().getOnlineTables().contains(indexTable)) throw new IllegalStateException(\"index table offline\");","typeGuard":"// narrow the wrapped cause to decide retry vs fail\nstatic boolean isTransientIndexFailure(PrestoException e) {\n    Throwable c = e.getCause();\n    return c instanceof org.apache.accumulo.core.client.TableOfflineException\n        || c instanceof java.io.IOException\n        || c instanceof org.apache.thrift.transport.TTransportException;\n}","tryCatchPattern":"try {\n    ranges = indexLookup.getIndexRanges(constraints);\n} catch (PrestoException e) {\n    if (isTransientIndexFailure(e)) {\n        ranges = retryWithBackoff(() -> indexLookup.getIndexRanges(constraints), 3);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always log e.getCause() first — the top-level message is generic","Monitor Accumulo tserver health and network latency from Presto workers","Keep the index table online and avoid maintenance windows during query load","Tune connector scan timeouts to match cluster size/latency"],"tags":["accumulo","presto","index-lookup","transient-failure"],"backgroundTag":"accumulo-scan-failure","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"}