apache/seatunnel · error · SeaTunnelException
PostgreSQL-CDC startup.mode 'COMMITTED_OFFSET' requires an e
Error message
PostgreSQL-CDC startup.mode 'COMMITTED_OFFSET' requires an explicit 'slot.name' option.
What it means
PostgresIncrementalSource.validateStartupOptions enforces that startup.mode = COMMITTED_OFFSET is paired with a non-empty slot.name option, because resuming from a committed LSN requires reading from a known replication slot. Missing or blank slot.name fails with SeaTunnelException.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/source/PostgresIncrementalSource.java:170
public Optional<String> driverName() {
return Optional.of("org.postgresql.Driver");
}
@Override
public List<SchemaChangeType> supports() {
return Collections.singletonList(SchemaChangeType.ADD_COLUMN);
}
private void validateStartupOptions(ReadonlyConfig options, StartupConfig startupConfig) {
if (startupConfig.getStartupMode() != StartupMode.COMMITTED_OFFSET) {
return;
}
Optional<String> slotName =
options.getOptional(PostgresIncrementalSourceOptions.SLOT_NAME)
.map(String::trim)
.filter(name -> !name.isEmpty());
if (!slotName.isPresent()) {
throw new SeaTunnelException(
String.format(
"PostgreSQL-CDC startup.mode '%s' requires an explicit '%s' option.",
StartupMode.COMMITTED_OFFSET,
PostgresIncrementalSourceOptions.SLOT_NAME.key()));
}
}
private void validateSchemaEvolutionOptions(ReadonlyConfig options) {
if (options.get(SourceOptions.SCHEMA_CHANGES_ENABLED)
&& !"pgoutput"
.equalsIgnoreCase(
options.get(
PostgresIncrementalSourceOptions.DECODING_PLUGIN_NAME))) {
throw new SeaTunnelException(
String.format(
"PostgreSQL-CDC schema evolution requires '%s = pgoutput' because PostgreSQL RELATION messages provide the changed schema.",
PostgresIncrementalSourceOptions.DECODING_PLUGIN_NAME.key()));
}View on GitHub (pinned to cf67b549a7)
Solutions
- Add slot.name = "<existing-slot>" to the PostgreSQL-CDC source options.
- Ensure the named slot exists in Postgres (SELECT * FROM pg_replication_slots;).
- Or choose a different startup.mode (e.g. INITIAL or LATEST_OFFSET) that doesn't require an explicit slot.
- Check for whitespace-only values that pass existence checks but fail this validation.
Example fix
// before startup.mode = "COMMITTED_OFFSET" // after startup.mode = "COMMITTED_OFFSET" slot.name = "seatunnel_slot"
Defensive patterns
Strategy: validation
Validate before calling
if ("COMMITTED_OFFSET".equals(startupMode) && (slotName == null || slotName.trim().isEmpty())) {
throw new IllegalArgumentException("COMMITTED_OFFSET requires a non-empty slot.name");
} Prevention
- Always set slot.name when using COMMITTED_OFFSET startup mode.
- Confirm the slot exists via pg_replication_slots before submitting.
- Validate connector options in CI with a schema/config linter.
When it happens
Trigger: Thrown from validateStartupOptions (via getStartupConfig) when startup.mode = 'COMMITTED_OFFSET' and the SLOT_NAME option is absent, empty, or whitespace-only.
Common situations: Users copying a sample config without slot.name; assuming the default slot applies; trimming/typo leaving an empty value.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Publication autocreation is disabled, please create one and
- No table filters found for filtered publication %s
- Invalid table name: ${tableStr} ,Postgres identifier is of t
- Table ${tableId} does not have a full replica identity, plea
- The %s mode is not supported.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/24882a6d3f51a86d.
Report an issue: GitHub.