{"record":{"id":"b11570be89cae09d","repo":"apache/cassandra","slug":"cannot-apply-a-transaction-with-savestatus-com","errorCode":null,"errorMessage":"Cannot apply a transaction with saveStatus \" + command.saveStatus()","messagePattern":"Cannot apply a transaction with saveStatus \" \\+ command\\.saveStatus\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java","lineNumber":1816,"sourceCode":"                            return Commands.applyChain(safeStore, command.asExecuted());\n                        Commands.maybeExecute(safeStore, safeCommand, command, true, true, NotifyWaitingOnPlus.adapter(ignore -> {}, true, true));\n                        return AsyncChains.success(null);\n                    });\n                    break;\n                case FORCE_UPDATE:\n                    run(txnId, commandStoreId, safeStore -> {\n                        SafeCommand safeCommand = safeStore.unsafeGet(txnId);\n                        safeCommand.update(safeStore, safeCommand.current(), true);\n                        return AsyncChains.success(null);\n                    });\n                    break;\n                case FORCE_APPLY:\n                    run(txnId, commandStoreId, safeStore -> {\n                        SafeCommand safeCommand = safeStore.unsafeGet(txnId);\n                        Command command = safeCommand.current();\n                        // TODO (expected): we can call applyChain with TruncatedApplyWithOutcome in theory, but the type signature prevents it\n                        if (command.saveStatus().compareTo(SaveStatus.PreApplied) < 0 || command.saveStatus().compareTo(SaveStatus.TruncatedApplyWithOutcome) >= 0)\n                            throw new UnsupportedOperationException(\"Cannot apply a transaction with saveStatus \" + command.saveStatus());\n                        return Commands.applyChain(safeStore, (Command.Executed) command);\n                    });\n                    break;\n                case FETCH:\n                    runWithRoute(txnId, commandStoreId, command -> {\n                        Timestamp executeAt = command.executeAtIfKnown();\n                        return (route, result) -> fetch(txnId, executeAt, route, result);\n                    });\n                    break;\n                case RECOVER:\n                    runWithRoute(txnId, commandStoreId, command -> (route, result) -> {\n                        recover(txnId, route, result);\n                    });\n                    break;\n                case REQUEUE_PROGRESS_LOG:\n                    run(txnId, commandStoreId, safeStore -> {\n                        ((DefaultProgressLog)safeStore.progressLog()).requeue(safeStore, TxnStateKind.Waiting, txnId);\n                        ((DefaultProgressLog)safeStore.progressLog()).requeue(safeStore, TxnStateKind.Home, txnId);","sourceCodeStart":1798,"sourceCodeEnd":1834,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java#L1798-L1834","documentation":"The FORCE_APPLY debug operation on accord_txn_ops can only be run when the target command's saveStatus is in the 'committed but not yet applied/truncated' window: at or after PreApplied is rejected, and at or after TruncatedApplyWithOutcome is rejected. This guard prevents force-applying a transaction whose state is outside the apply path, which would corrupt Accord command state.","triggerScenarios":"INSERTing a FORCE_APPLY row into system_views.accord_txn_ops for a txnId whose current command.saveStatus() is earlier than PreApplied (e.g. PreCommitted/Committed variants below the apply threshold) or already TruncatedApplyWithOutcome or later.","commonSituations":"Debugging a stuck transaction and force-applying before it has actually been committed; retrying FORCE_APPLY on a txn that has already been truncated by the epilogue; picking a txnId by eye from a debug table without checking its saveStatus.","solutions":["Check the command's saveStatus first (via the accord debug command table) and only run FORCE_APPLY when it is in [PreApplied, TruncatedApplyWithOutcome).","For commands earlier in the lifecycle, use the appropriate debug op (e.g. FETCH or a commit op) instead of FORCE_APPLY.","For already-truncated commands, use TruncatedApply-related ops rather than plain applyChain."],"exampleFix":"// before\nINSERT INTO system_views.accord_txn_ops (txn_id, op) VALUES ('<txnId>', 'FORCE_APPLY'); -- saveStatus = PreCommitted\n// after\n-- first confirm saveStatus is in range, or advance it first\nINSERT INTO system_views.accord_txn_ops (txn_id, op) VALUES ('<txnId>', 'FETCH');","handlingStrategy":"validation","validationCode":"// Check the command's saveStatus before issuing FORCE_APPLY\nObject status = debugTableLookup(\"accord_commands\", txnId, \"save_status\");\nif (status == null) throw new IllegalStateException(\"txn unknown\");\nboolean inRange = compare(status, \">=\", \"PreApplied\") && compare(status, \"<\", \"TruncatedApplyWithOutcome\");\nif (!inRange) throw new IllegalStateException(\"FORCE_APPLY not allowed for saveStatus \" + status);","typeGuard":null,"tryCatchPattern":"// cqlsh / tooling\ntry {\n    session.execute(forceApplyInsert);\n} catch (InvalidQueryException | DriverException e) {\n    if (e.getMessage().contains(\"Cannot apply a transaction with saveStatus\")) {\n        // re-check saveStatus and use the correct lifecycle op\n    }\n}","preventionTips":["Always read the command's saveStatus from the accord debug tables before FORCE_APPLY.","Understand the SaveStatus ordering: only the window [PreApplied, TruncatedApplyWithOutcome) is applyable.","For truncated commands use the truncated-apply ops, not FORCE_APPLY."],"tags":["accord","save-status","invalid-state","debug-ops"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}