{"record":{"id":"24882a6d3f51a86d","repo":"apache/seatunnel","slug":"postgresql-cdc-startup-mode-committed-offset-req","errorCode":null,"errorMessage":"PostgreSQL-CDC startup.mode 'COMMITTED_OFFSET' requires an explicit 'slot.name' option.","messagePattern":"PostgreSQL-CDC startup\\.mode 'COMMITTED_OFFSET' requires an explicit 'slot\\.name' option\\.","errorType":"validation","errorClass":"SeaTunnelException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/source/PostgresIncrementalSource.java","lineNumber":170,"sourceCode":"    public Optional<String> driverName() {\n        return Optional.of(\"org.postgresql.Driver\");\n    }\n\n    @Override\n    public List<SchemaChangeType> supports() {\n        return Collections.singletonList(SchemaChangeType.ADD_COLUMN);\n    }\n\n    private void validateStartupOptions(ReadonlyConfig options, StartupConfig startupConfig) {\n        if (startupConfig.getStartupMode() != StartupMode.COMMITTED_OFFSET) {\n            return;\n        }\n        Optional<String> slotName =\n                options.getOptional(PostgresIncrementalSourceOptions.SLOT_NAME)\n                        .map(String::trim)\n                        .filter(name -> !name.isEmpty());\n        if (!slotName.isPresent()) {\n            throw new SeaTunnelException(\n                    String.format(\n                            \"PostgreSQL-CDC startup.mode '%s' requires an explicit '%s' option.\",\n                            StartupMode.COMMITTED_OFFSET,\n                            PostgresIncrementalSourceOptions.SLOT_NAME.key()));\n        }\n    }\n\n    private void validateSchemaEvolutionOptions(ReadonlyConfig options) {\n        if (options.get(SourceOptions.SCHEMA_CHANGES_ENABLED)\n                && !\"pgoutput\"\n                        .equalsIgnoreCase(\n                                options.get(\n                                        PostgresIncrementalSourceOptions.DECODING_PLUGIN_NAME))) {\n            throw new SeaTunnelException(\n                    String.format(\n                            \"PostgreSQL-CDC schema evolution requires '%s = pgoutput' because PostgreSQL RELATION messages provide the changed schema.\",\n                            PostgresIncrementalSourceOptions.DECODING_PLUGIN_NAME.key()));\n        }","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/source/PostgresIncrementalSource.java#L152-L188","documentation":"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.","triggerScenarios":"Thrown from validateStartupOptions (via getStartupConfig) when startup.mode = 'COMMITTED_OFFSET' and the SLOT_NAME option is absent, empty, or whitespace-only.","commonSituations":"Users copying a sample config without slot.name; assuming the default slot applies; trimming/typo leaving an empty value.","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."],"exampleFix":"// before\nstartup.mode = \"COMMITTED_OFFSET\"\n// after\nstartup.mode = \"COMMITTED_OFFSET\"\nslot.name = \"seatunnel_slot\"","handlingStrategy":"validation","validationCode":"if (\"COMMITTED_OFFSET\".equals(startupMode) && (slotName == null || slotName.trim().isEmpty())) {\n  throw new IllegalArgumentException(\"COMMITTED_OFFSET requires a non-empty slot.name\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["postgres","cdc","config","startup-mode"],"backgroundTag":"missing-required-config-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}