apache/seatunnel · error · IllegalArgumentException

event payload must not be null

Error message

event payload must not be null

What it means

SqliteWalStore.append() requires each EdgeEvent to carry a non-null payload byte array, since the payload is what is persisted into the WAL table. A null payload cannot be meaningfully appended and would break replay, so append() throws this IllegalArgumentException before starting the transaction.

Solutions

  1. Ensure the payload is set — pass an empty byte[0] instead of null for empty events before calling append().
  2. Fix the upstream serializer/codec so it emits empty arrays rather than null payloads.
  3. Validate event.getPayload() != null at the producer boundary before appending.
  4. Check where the EdgeEvent was constructed; a missing payload usually indicates a skipped assignment.

Example fix

// before
byte[] payload = decode(body); // may return null
store.append(new EdgeEvent(type, payload));
// after
byte[] payload = decode(body);
store.append(new EdgeEvent(type, payload == null ? new byte[0] : payload));
Defensive patterns

Strategy: type-guard

Validate before calling

if (event.getPayload() == null) { event = event.withPayload(new byte[0]); }

Type guard

boolean hasPayload(EdgeEvent e) { return e.getPayload() != null; }

Try / catch

try { store.append(event); } catch (IllegalArgumentException e) { if (e.getMessage().contains("payload must not be null")) { store.append(event.withPayload(new byte[0])); } else { throw e; } }

Prevention

When it happens

Trigger: Calling walStore.append(event) with an EdgeEvent whose getPayload() returns null — e.g. an event constructed without payload bytes, or an upstream serializer that produced null for an empty message.

Common situations: Producers forwarding deserialized messages where empty bodies became null; building EdgeEvent objects by hand and forgetting setPayload; a codec that returns null instead of byte[0] for empty content.

Related errors


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

Appendix: source

Thrown at seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/wal/sqlite/SqliteWalStore.java:72

        this.sourcePositionStore = new SqliteSourcePositionStore(connection, false);
    }

    public SqliteWalStore(Connection connection, boolean closeConnection) {
        this.connection = Objects.requireNonNull(connection, "connection");
        this.closeConnection = closeConnection;
        this.sourcePositionStore = new SqliteSourcePositionStore(connection, false);
    }

    @Override
    public EdgeSourcePositionStore sourcePositionStore() {
        return sourcePositionStore;
    }

    @Override
    public long append(EdgeEvent event) throws Exception {
        byte[] payload = event.getPayload();
        if (payload == null) {
            throw new IllegalArgumentException("event payload must not be null");
        }
        long now = System.currentTimeMillis();
        boolean autoCommit = connection.getAutoCommit();
        connection.setAutoCommit(false);
        try {
            long batchId = SqliteBatchIdAllocator.allocateNext(connection);
            try (PreparedStatement statement =
                    connection.prepareStatement(
                            WalSqlStatements.INSERT, Statement.RETURN_GENERATED_KEYS)) {
                statement.setString(1, event.getSourceId());
                statement.setBytes(2, payload);
                statement.setLong(3, event.getEventTime());
                statement.setBytes(4, MetadataSerde.serialize(event.getMetadata()));
                statement.setString(5, WalRecordStatus.PENDING.name());
                statement.setInt(6, 0);
                statement.setLong(7, now);
                statement.setLong(8, now);
                statement.setLong(9, batchId);

View on GitHub (pinned to cf67b549a7)