Skip to content

Handle bad records with a dead-letter topic

A record that is not valid Protobuf (or whose schema cannot be resolved) is a poison record. By default it fails the task. Set on-deserialize-error to skip to drop it, and add a dead-letter-topic to keep its raw bytes for inspection.

CREATE TABLE orders (
  order_id STRING,
  amount   DOUBLE
) WITH (
  'connector' = 'kafka',
  'topic' = 'orders',
  'properties.bootstrap.servers' = 'kafka:9092',

  'value.format' = 'proto-confluent',
  'value.proto-confluent.url' = 'http://schema-registry:8081',
  'value.proto-confluent.topic' = 'orders',
  'value.proto-confluent.on-deserialize-error' = 'skip',
  'value.proto-confluent.dead-letter-topic' = 'orders-dlq',
  'value.proto-confluent.dead-letter.properties' = 'bootstrap.servers:''kafka:9092'''
);

Each dead-letter record carries the original bytes plus error.class, error.message and source.topic headers. The numDeserializeErrors metric counts every skipped record.

bootstrap.servers is required for the topic to be written

Without dead-letter.properties containing bootstrap.servers, no producer is created: failures are only logged and counted, and a WARN is logged at open.

Quote values that contain a colon

Map options split each pair on :, so a host:port value must be quoted with doubled single quotes inside the SQL string, as in the example above. Unquoted, table creation fails with Map item is not a key-value pair (missing ':'?).

Only fail is fatal

on-deserialize-error is matched case-insensitively and any value other than fail — including a typo — takes the skip path.

Watch it happen in the dead-letter demo.