{"record":{"id":"4b533735c7ed9ef9","repo":"apache/seatunnel","slug":"refusing-write-without-yes","errorCode":null,"errorMessage":"Refusing write without --yes","messagePattern":"Refusing write without --yes","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/command/db/EdgeAgentDbCommand.java","lineNumber":336,"sourceCode":"        DbWriteGuard.requireWriteAllowed(paths, cli);\n        if (cli.getOlderThanMs() <= 0L) {\n            throw new IllegalArgumentException(\n                    \"wal-purge-acked requires --older-than-ms <positive-ms>\");\n        }\n        long cutoff = System.currentTimeMillis() - cli.getOlderThanMs();\n        try (EdgeAgentDbConnection db =\n                EdgeAgentDbConnection.openReadWrite(paths.getSqlitePath())) {\n            long count = countAckedBefore(db, cutoff);\n            if (cli.isDryRun()) {\n                System.out.println(\n                        \"DRY-RUN: would delete \"\n                                + count\n                                + \" ACKED rows with updated_at < \"\n                                + cutoff);\n                return;\n            }\n            if (!cli.isYes()) {\n                throw new IllegalArgumentException(\"Refusing write without --yes\");\n            }\n            try (PreparedStatement statement =\n                    db.getConnection().prepareStatement(EdgeAgentDbSql.WAL_PURGE_ACKED_BEFORE)) {\n                statement.setString(1, WalRecordStatus.ACKED.name());\n                statement.setLong(2, cutoff);\n                int deleted = statement.executeUpdate();\n                System.out.println(\n                        \"Deleted \" + deleted + \" ACKED rows (updated_at < \" + cutoff + \")\");\n            }\n        }\n    }\n\n    private long countAckedBefore(EdgeAgentDbConnection db, long cutoff) throws SQLException {\n        try (PreparedStatement statement =\n                db.getConnection().prepareStatement(EdgeAgentDbSql.WAL_COUNT_ACKED_BEFORE)) {\n            statement.setString(1, WalRecordStatus.ACKED.name());\n            statement.setLong(2, cutoff);\n            try (ResultSet rs = statement.executeQuery()) {","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/command/db/EdgeAgentDbCommand.java#L318-L354","documentation":"After passing the write guard and counting affected rows, runWalPurgeAcked performs the actual DELETE only when --yes is set. If rows matched the cutoff but the user has not confirmed with --yes (and was not in --dry-run, which returned earlier), the command throws IllegalArgumentException instead of mutating the database.","triggerScenarios":"Running wal-purge-acked with --yes omitted while at least one ACKED row matches the cutoff; programmatic invocation with a Cli options object whose isYes() is false.","commonSituations":"Programmatic callers constructing a Cli with dry-run=false but yes unset; users whose earlier zero-row runs never reached the write step, then hit this once rows exist.","solutions":["Re-run the command with --yes to authorize the deletion.","Run with --dry-run first to see how many ACKED rows would be deleted, then confirm with --yes.","In programmatic callers, set yes=true only after the operator has confirmed."],"exampleFix":"// before\nagent db wal-purge-acked --older-than-ms 86400000\n// after\nagent db wal-purge-acked --older-than-ms 86400000 --yes","handlingStrategy":"validation","validationCode":"# bash wrapper: confirm before non-dry-run purge\nif [[ \" $* \" != *' --yes '* && \" $* \" != *' --dry-run '* ]]; then\n  read -p \"Apply wal-purge-acked? Type YES: \" c && [[ $c == YES ]] && set -- \"$@\" --yes\nfi","typeGuard":null,"tryCatchPattern":"try {\n  walPurgeAcked(cli);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"--yes\")) {\n    log.info(\"Purge not applied; run again with --yes after reviewing --dry-run output\");\n  }\n}","preventionTips":["Preview with --dry-run (which prints the row count) before every real purge.","Gate scripts on the count from --dry-run before adding --yes.","Keep the guard in place in programmatic Cli construction — set yes only after explicit confirmation."],"tags":["cli","safety-guard","write-operations","confirmation"],"backgroundTag":"missing-required-flag","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}