alibaba/canal · error · IOException

end of stream when reading header

Error message

end of stream when reading header

What it means

Thrown by the read() helper when channel.read() returns -1, meaning the remote end closed the connection before the full header buffer was filled. The connector treats truncated reads as fatal.

Source

Thrown at admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java:309

        writeHeader.flip();
        channel.write(writeHeader);
        channel.write(ByteBuffer.wrap(body));
    }

    private byte[] readNextPacket(ReadableByteChannel channel) throws IOException {
        readHeader.clear();
        read(channel, readHeader);
        int bodyLen = readHeader.getInt(0);
        ByteBuffer bodyBuf = ByteBuffer.allocate(bodyLen).order(ByteOrder.BIG_ENDIAN);
        read(channel, bodyBuf);
        return bodyBuf.array();
    }

    private void read(ReadableByteChannel channel, ByteBuffer buffer) throws IOException {
        while (buffer.hasRemaining()) {
            int r = channel.read(buffer);
            if (r == -1) {
                throw new IOException("end of stream when reading header");
            }
        }
    }

    private void quietlyClose(Channel channel) {
        try {
            channel.close();
        } catch (IOException e) {
            logger.warn("exception on closing channel:{} \n {}", channel, e);
        }
    }
}

View on GitHub (pinned to 87be50e876)

Solutions

  1. Check that the canal-server is running and reachable (telnet/ping the admin port).
  2. Increase soTimeout if the idle timeout is closing the socket before operations complete.
  3. Reconnect (the connector resets on disconnect) and retry the operation idempotently.
  4. Inspect server logs for crashes/OOM/abrupt shutdowns coinciding with the disconnect.
Defensive patterns

Strategy: retry

Try / catch

try {
    connector.doX();
} catch (ServiceException e) {
    if (e.getCause() instanceof IOException && e.getCause().getMessage().contains("end of stream")) {
        // server closed socket; reconnect and retry idempotent op once
    }
    throw e;
}

Prevention

When it happens

Trigger: Any readNextPacket() call where the canal-server closes/resets the socket mid-packet (during handshake, auth, or an admin operation), so the 4-byte header read loop hits EOF.

Common situations: Server crash or restart mid-operation; network interruption; server-side timeout closing idle connections; firewall/proxy dropping the long-lived admin socket; the soTimeout elapsed and the socket was torn down.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/a8abe234da77e782. Report an issue: GitHub.