apache/seatunnel · error · SeaTunnelRuntimeException

API-09

API-09

Error message

Handle save mode failed

What it means

SinkExecuteProcessor.handleSaveMode applies schema/data save-mode actions via a SaveModeHandler; any exception inside handler.open() or SaveModeExecuteWrapper.execute() is wrapped in a SeaTunnelRuntimeException with code HANDLE_SAVE_MODE_FAILED (API-09).

Source

Thrown at seatunnel-core/seatunnel-spark-starter/seatunnel-spark-2-starter/src/main/java/org/apache/seatunnel/core/starter/spark/execution/SinkExecuteProcessor.java:226

        if (createdAnySink && !skippedTables.isEmpty()) {
            log.warn(
                    MultiTableFailureHelper.formatFailedTableSummary(
                            "Some sink tables were skipped in Spark starter.", skippedTables));
        }
        // the sink is the last stream
        return null;
    }

    public void handleSaveMode(SeaTunnelSink sink) {
        if (sink instanceof SupportSaveMode) {
            Optional<SaveModeHandler> saveModeHandler =
                    ((SupportSaveMode) sink).getSaveModeHandler();
            if (saveModeHandler.isPresent()) {
                try (SaveModeHandler handler = saveModeHandler.get()) {
                    handler.open();
                    new SaveModeExecuteWrapper(handler).execute();
                } catch (Exception e) {
                    throw new SeaTunnelRuntimeException(HANDLE_SAVE_MODE_FAILED, e);
                }
            }
        }
    }

    private boolean shouldContinueOtherTables() {
        return MultiTableFailureHelper.shouldContinueOtherTables(
                ReadonlyConfig.fromConfig(sparkRuntimeEnvironment.getConfig()));
    }

    private RuntimeException wrapThrowable(Throwable error) {
        if (error instanceof RuntimeException) {
            return (RuntimeException) error;
        }
        return new RuntimeException(error);
    }

    private void logSkippedTable(

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Read the wrapped cause for the underlying save-mode failure
  2. Ensure required drivers are on the classpath (add to env jars)
  3. Verify credentials/permissions for schema creation or data manipulation on the target
  4. Test the save-mode handler's target connection independently before running the job

Example fix

// before
env {
  jars = []
}
// after
env {
  jars = "file:///opt/seatunnel/connectors/mysql-connector-java-8.0.x.jar"
}
Defensive patterns

Strategy: try-catch

Validate before calling

try (SaveModeHandler h = handler) {
    h.open();
} catch (Exception e) {
    precheckFailure(e); // surface driver/connection problems before the job
}

Try / catch

try {
    sinkProcessor.execute();
} catch (SeaTunnelRuntimeException e) {
    if ("API-09".equals(e.getSeaTunnelErrorCode().getCode())) {
        log.error("Save mode failed, cause:", e.getCause());
    }
}

Prevention

When it happens

Trigger: Executing save-mode operations (auto-create tables, execute DDL/data in save-mode jar) fails — e.g. driver/credentials issues, DDL errors, connection failure while opening the handler.

Common situations: Missing JDBC driver on the Spark classpath; insufficient privileges to create tables; save-mode custom SQL failing; target database unreachable.

Related errors


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