{"record":{"id":"2eaf88f3f9e98fd4","repo":"apache/seatunnel","slug":"batchid-must-be-positive","errorCode":null,"errorMessage":"batchId must be positive","messagePattern":"batchId must be positive","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-edge-agent/seatunnel-edge-agent-transport/src/main/java/org/apache/seatunnel/edge/agent/transport/socket/EdgeSocketLineTransport.java","lineNumber":43,"sourceCode":"\nfinal class EdgeSocketLineTransport {\n\n    private final EdgeTransportConfig config;\n\n    EdgeSocketLineTransport(EdgeTransportConfig config) {\n        this.config = config;\n    }\n\n    void authenticate(BufferedReader reader, BufferedWriter writer) throws IOException {\n        writeLine(writer, EdgeSocketProtocol.AUTH_LINE_PREFIX + config.getToken());\n        handleAuthResponse(readLineNormalized(reader));\n    }\n\n    void sendBatchUntilReceived(\n            BufferedReader reader, BufferedWriter writer, long batchId, String payload)\n            throws IOException, InterruptedException {\n        if (batchId <= 0) {\n            throw new IllegalArgumentException(\"batchId must be positive\");\n        }\n        String line = EdgeSocketProtocol.BATCH_PREFIX + batchId + ':' + payload;\n        int attempts = 0;\n        while (attempts < config.getMaxBatchSendAttempts()) {\n            writeLine(writer, line);\n            String reply = readLineNormalized(reader);\n            if (EdgeSocketProtocol.RESP_RECEIVED.equals(reply)) {\n                return;\n            }\n            if (EdgeSocketProtocol.RESP_RETRY.equals(reply)) {\n                attempts++;\n                EdgeTransportConfig.sleepQuiet(\n                        EdgeTransportConfig.computeBackoffMillis(\n                                attempts - 1,\n                                config.getInitialBackoffMs(),\n                                config.getMaxBackoffMs()));\n                continue;\n            }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-edge-agent/seatunnel-edge-agent-transport/src/main/java/org/apache/seatunnel/edge/agent/transport/socket/EdgeSocketLineTransport.java#L25-L61","documentation":"EdgeSocketLineTransport.sendBatchUntilReceived validates its batchId argument before writing the BATCH line to the socket. A batchId of zero or negative is rejected with this IllegalArgumentException because the wire protocol requires a positive, monotonically increasing batch identifier so the collector can deduplicate and order batches.","triggerScenarios":"Calling sendBatchUntilReceived (or the higher-level EdgeTransportClient.send) with batchId <= 0, e.g. an uninitialized/zero batch counter or a counter reset to 0/−1 after restart.","commonSituations":"Batch id counter initialized to 0 and never incremented before first send; persisted counter restored incorrectly after agent restart; integer overflow wrapping to negative in long-running agents.","solutions":["Initialize the batch counter to 1 (or verify it is incremented before the first send)","Check the code path that generates batchId and add an assertion/validation at generation time","If a persisted counter is used, verify the restore logic does not yield 0 on a fresh start","Clamp or regenerate: if batchId <= 0, assign a new positive value before calling send"],"exampleFix":"// before\nclient.send(batchId, payload); // batchId may be 0\n// after\nif (batchId <= 0) { batchId = nextBatchId(); }\nclient.send(batchId, payload);","handlingStrategy":"validation","validationCode":"if (batchId <= 0) throw new IllegalArgumentException(\"batchId must be positive, got \" + batchId);","typeGuard":null,"tryCatchPattern":"try { client.send(batchId, payload); } catch (IllegalArgumentException e) { batchId = counter.next(); client.send(batchId, payload); }","preventionTips":["Start batch counters at 1, never 0","Increment the counter before the first send, not after","Validate restored persisted counters on startup","Use an AtomicLong starting at 1 for the counter"],"tags":["validation","argument","batch-id"],"backgroundTag":"invalid-argument-value","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"}