apache/seatunnel · error · IOException

Unexpected batch response

Error message

Unexpected batch response: ${reply} (expected RECEIVED, RETRY, or QUEUE_FULL<ms>)

What it means

sendBatchUntilReceived recognizes only RECEIVED, RETRY, and QUEUE_FULL<ms> replies from the collector. Any other reply line is treated as a protocol violation and thrown as this IOException including the raw reply text. It indicates the server sent something unexpected on the batch channel.

Solutions

  1. Read the reply value embedded in the exception message to identify what the server actually returned
  2. Verify the agent connects to the correct host/port running the EdgeSocket collector
  3. Check that collector and agent use compatible SeaTunnel versions and the same EdgeSocket protocol
  4. If the reply is a legitimate server status, extend the client/protocol handling on both sides consistently
Defensive patterns

Strategy: try-catch

Try / catch

try { client.send(batchId, payload); } catch (IOException e) { if (e.getMessage().startsWith("Unexpected batch response:")) { log.error("Collector protocol violation: {}", e.getMessage()); } throw e; }

Prevention

When it happens

Trigger: The collector responds to a BATCH line with an unrecognized token — e.g. an error message, an HTML error page from a misconfigured port, AUTH_FAILED/DECRYPT_FAILED variants not matched, or a version-mismatched protocol reply.

Common situations: Pointing the agent at a wrong service/port that replies with non-protocol text; collector running an older/newer protocol version; server-side error text instead of a protocol reply; extra whitespace or BOM in the reply.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/a5f1462c56a4d764. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-edge-agent/seatunnel-edge-agent-transport/src/main/java/org/apache/seatunnel/edge/agent/transport/socket/EdgeSocketLineTransport.java:73

                EdgeTransportConfig.sleepQuiet(
                        EdgeTransportConfig.computeBackoffMillis(
                                attempts - 1,
                                config.getInitialBackoffMs(),
                                config.getMaxBackoffMs()));
                continue;
            }
            if (reply.startsWith(EdgeSocketProtocol.RESP_QUEUE_FULL_PREFIX)) {
                long waitMs = parseQueueFullBackoffMs(reply);
                EdgeTransportConfig.sleepQuiet(waitMs);
                continue;
            }
            if (EdgeSocketProtocol.RESP_DECRYPT_FAILED.equals(reply)) {
                throw new IOException(
                        "Edge socket ingress decryption failed (DECRYPT_FAILED): verify "
                                + "output.aes-secret-key-base64 matches EdgeSocket source "
                                + "secret_key");
            }
            throw new IOException(
                    "Unexpected batch response: "
                            + reply
                            + " (expected "
                            + EdgeSocketProtocol.RESP_RECEIVED
                            + ", "
                            + EdgeSocketProtocol.RESP_RETRY
                            + ", or "
                            + EdgeSocketProtocol.RESP_QUEUE_FULL_PREFIX
                            + "<ms>)");
        }
        throw new IOException(
                "Exceeded maxBatchSendAttempts="
                        + config.getMaxBatchSendAttempts()
                        + " without RECEIVED for batch "
                        + batchId);
    }

    private static void handleAuthResponse(String reply) throws IOException {

View on GitHub (pinned to cf67b549a7)