{"record":{"id":"cbd2e3c1cf6310b9","repo":"apache/seatunnel","slug":"api-09","errorCode":"API-09","errorMessage":"Handle save mode failed","messagePattern":"Handle save mode failed","errorType":"error_code","errorClass":"SeaTunnelRuntimeException","httpStatus":null,"severity":"error","filePath":"seatunnel-core/seatunnel-flink-starter/seatunnel-flink-13-starter/src/main/java/org/apache/seatunnel/core/starter/flink/execution/SinkExecuteProcessor.java","lineNumber":268,"sourceCode":"        }\n        if (sinks.values().stream().anyMatch(sink -> !(sink instanceof SupportMultiTableSink))) {\n            LOGGER.info(\"Unsupported multi table sink api, rollback to sink template\");\n            // choose the first sink\n            return sinks.values().iterator().next();\n        }\n        return FactoryUtil.createMultiTableSink(sinks, sinkConfig, classLoader);\n    }\n\n    public void handleSaveMode(SeaTunnelSink seaTunnelSink) {\n        if (seaTunnelSink instanceof SupportSaveMode) {\n            SupportSaveMode saveModeSink = (SupportSaveMode) seaTunnelSink;\n            Optional<SaveModeHandler> saveModeHandler = saveModeSink.getSaveModeHandler();\n            if (saveModeHandler.isPresent()) {\n                try (SaveModeHandler handler = saveModeHandler.get()) {\n                    handler.open();\n                    new SaveModeExecuteWrapper(handler).execute();\n                } catch (Exception e) {\n                    throw new SeaTunnelRuntimeException(HANDLE_SAVE_MODE_FAILED, e);\n                }\n            }\n        }\n    }\n\n    private boolean shouldContinueOtherTables() {\n        return MultiTableFailureHelper.shouldContinueOtherTables(\n                ReadonlyConfig.fromConfig(envConfig));\n    }\n\n    private RuntimeException wrapThrowable(Throwable error) {\n        if (error instanceof RuntimeException) {\n            return (RuntimeException) error;\n        }\n        return new RuntimeException(error);\n    }\n\n    private void logSkippedTable(","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-core/seatunnel-flink-starter/seatunnel-flink-13-starter/src/main/java/org/apache/seatunnel/core/starter/flink/execution/SinkExecuteProcessor.java#L250-L286","documentation":"SeaTunnelRuntimeException with code API-09 thrown by handleSaveMode when executing a sink's SaveModeHandler (auto table creation / schema evolution) throws any exception. The library wraps the original error to attribute it to the save-mode step so users know the sink never received data — pre-write DDL failed.","triggerScenarios":"A sink implementing SupportsSaveMode returns a SaveModeHandler; handler.open() or SaveModeExecuteWrapper.execute() fails — e.g. DDL statement rejected by the target database, insufficient privileges, or connection failure during table creation — inside handleSaveMode called from execute.","commonSituations":"Target database user lacks CREATE/ALTER privileges; schema-reflect DDL incompatible with the target DB dialect; network/credentials failure while opening the catalog connection.","solutions":["Inspect the wrapped cause 'e' for the actual database/DDL error","Grant the DB user CREATE/ALTER privileges or pre-create the table manually and use save_mode accordingly","Fix save_mode config (e.g. invalid custom DDL in save_mode templates) to match the target dialect"],"exampleFix":"# before\nsave_mode {\n  custom_sql = \"CREATE TABEL t (...)\"  # typo\n}\n# after\nsave_mode {\n  custom_sql = \"CREATE TABLE t (...)\"\n}","handlingStrategy":"try-catch","validationCode":"// check DDL privileges beforehand\ntry (Connection c = dataSource.getConnection()) {\n    DatabaseMetaData md = c.getMetaData();\n    boolean canCreate = !c.getMetaData().getTableTypes().next() == false; // probe via test DDL instead\n}","typeGuard":null,"tryCatchPattern":"try {\n    sink.execute(...);\n} catch (SeaTunnelRuntimeException e) {\n    if (\"API-09\".equals(e.getSeaTunnelErrorCode().getCode())) {\n        Throwable root = e.getCause(); // real DDL/DB failure\n        log.error(\"Save mode failed: {}\", root.getMessage());\n    }\n}","preventionTips":["Grant CREATE/ALTER privileges to the sink database user","Dry-run save_mode custom SQL against the target database","Pre-create target tables to minimize save-mode work"],"tags":["save-mode","sink","ddl"],"backgroundTag":"database-write-failed","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"}