{"record":{"id":"ad1411a5ca1424d9","repo":"apache/cassandra","slug":"sstable-is-not-pending-repair","errorCode":null,"errorMessage":"sstable is not pending repair","messagePattern":"sstable is not pending repair","errorType":"exception","errorClass":"IllegalSSTableArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/compaction/PendingRepairManager.java","lineNumber":129,"sourceCode":"            {\n                strategy = get(id);\n\n                if (strategy == null)\n                {\n                    logger.debug(\"Creating {}.{} compaction strategy for pending repair: {}\", cfs.metadata.keyspace, cfs.metadata.name, id);\n                    strategy = cfs.createCompactionStrategyInstance(params);\n                    strategies = mapBuilder().putAll(strategies).put(id, strategy).build();\n                }\n            }\n        }\n        return strategy;\n    }\n\n    private static void checkPendingID(TimeUUID pendingID)\n    {\n        if (pendingID == null)\n        {\n            throw new IllegalSSTableArgumentException(\"sstable is not pending repair\");\n        }\n    }\n\n    AbstractCompactionStrategy getOrCreate(SSTableReader sstable)\n    {\n        return getOrCreate(sstable.getSSTableMetadata().pendingRepair);\n    }\n\n    private synchronized void removeSessionIfEmpty(TimeUUID sessionID)\n    {\n        if (!strategies.containsKey(sessionID) || !strategies.get(sessionID).getSSTables().isEmpty())\n            return;\n\n        logger.debug(\"Removing compaction strategy for pending repair {} on  {}.{}\", sessionID, cfs.metadata.keyspace, cfs.metadata.name);\n        strategies = ImmutableMap.copyOf(Maps.filterKeys(strategies, k -> !k.equals(sessionID)));\n    }\n\n    synchronized void removeSSTable(SSTableReader sstable)","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/compaction/PendingRepairManager.java#L111-L147","documentation":"PendingRepairManager APIs (getOrCreate, getScanners) require a non-null pending repair ID because they manage only incremental-repair SSTables. checkPendingID throws IllegalSSTableArgumentException when a null ID is passed, indicating the caller passed an sstable that is not part of any pending repair.","triggerScenarios":"Calling PendingRepairManager.getOrCreate or getScanners with an sstable whose metadata pendingRepair is null (a regular, non-incremental-repair sstable).","commonSituations":"Custom compaction/repair tooling sending ordinary SSTables into the pending-repair path; race where a repair session finished and promoted/cleared the pendingRepair ID before the call; incremental repair misconfiguration.","solutions":["Only pass SSTables with a non-null sstable.getSSTableMetadata().pendingRepair into PendingRepairManager","Re-read sstable metadata to ensure the repair session has not completed and cleared the ID between selection and use","Route non-repair SSTables to the normal compaction strategy instead","If hit in stock Cassandra operation, capture nodetool tpstats/repair_admin output and file a bug"],"exampleFix":"// before\nmanager.getScanners(pendingRepairId, sstables);\n// after\nif (pendingRepairId == null) { regularStrategyScanners(sstables); } else { manager.getScanners(pendingRepairId, sstables); }","handlingStrategy":"type-guard","validationCode":"if (sstable.getSSTableMetadata().pendingRepair == null)\n    throw new IllegalArgumentException(\"sstable \" + sstable + \" is not pending repair; use regular compaction path\");","typeGuard":"static boolean isPendingRepair(SSTableReader sstable) {\n    return sstable.getSSTableMetadata().pendingRepair != null;\n}","tryCatchPattern":"try {\n    manager.getScanners(pendingId, sstables);\n} catch (IllegalSSTableArgumentException e) {\n    // fall back to the default compaction strategy scanners\n    regularStrategy.getScanners(sstables, null);\n}","preventionTips":["Check sstable metadata pendingRepair before routing to PendingRepairManager","Re-fetch metadata if time passed since sstable selection (repair may have completed)","Route non-repair sstables to the standard compaction strategy","Keep repair sessions alive until all derived compaction work is submitted"],"tags":["compaction","incremental-repair","argument-validation"],"backgroundTag":"null-argument","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}