apache/seatunnel · error · PaimonConnectorException

UNSUPPORTED_BRANCH_SAVE_MODE

UNSUPPORTED_BRANCH_SAVE_MODE

Error message

Paimon branch '${branch}' does not support this save mode for table '${tablePath}'. The main table must exist before writing to a non-main branch.

What it means

When writing to a non-main Paimon branch, the main table must already exist; branch writes operate on an existing table's branch, not a fresh one. If the main table is absent, save-mode handling cannot proceed safely and throws UNSUPPORTED_BRANCH_SAVE_MODE.

Source

Thrown at seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/handler/PaimonSaveModeHandler.java:96

    }

    @Override
    public void handleSchemaSaveModeWithRestore() {
        checkBranchSaveMode();
        super.handleSchemaSaveModeWithRestore();
    }

    private boolean isNonMainBranch() {
        return StringUtils.isNotEmpty(branch)
                && !BranchManager.DEFAULT_MAIN_BRANCH.equalsIgnoreCase(branch);
    }

    private void checkBranchSaveMode() {
        if (!isNonMainBranch()) {
            return;
        }
        if (!catalog.tableExists(tablePath)) {
            throw unsupportedBranchSaveMode(
                    "The main table must exist before writing to a non-main branch.");
        }
        Table paimonTable = ((PaimonCatalog) catalog).getPaimonTable(tablePath);
        if (!((FileStoreTable) paimonTable).branchManager().branchExists(branch)) {
            throw new PaimonConnectorException(
                    PaimonConnectorErrorCode.BRANCH_NOT_EXISTS,
                    String.format(
                            "Specified branch '%s' of table '%s' does not exist.",
                            branch, tablePath));
        }
        if (this.schemaSaveMode == SchemaSaveMode.RECREATE_SCHEMA) {
            throw unsupportedBranchSaveMode(
                    "schema_save_mode=RECREATE_SCHEMA would drop and recreate the main table.");
        }
        if (this.dataSaveMode == DataSaveMode.DROP_DATA) {
            throw unsupportedBranchSaveMode(
                    "data_save_mode=DROP_DATA would truncate the main table.");
        }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Create the main table first (e.g. via catalog/CREATE TABLE or a prior job writing to the main branch), then write to the branch
  2. Remove the branch option or set it to 'main' for the initial table creation run
  3. Verify the table path spelling matches an existing table

Example fix

// before: first run directly on a branch
sink { Paimon { branch = "audit", schema_save_mode = CREATE_SCHEMA_WHEN_NOT_EXIST } }
// after: create main table first, then branch write
sink { Paimon { schema_save_mode = CREATE_SCHEMA_WHEN_NOT_EXIST } } // run once on main
sink { Paimon { branch = "audit" } } // then write to branch
Defensive patterns

Strategy: validation

Validate before calling

// before running a branch write, ensure the main table exists
// via Paimon catalog:
if (!catalog.tableExists(TablePath.of("db.db.tbl"))) {
    catalog.createTable(TablePath.of("db.db.tbl"), schema, partitions, props);
}

Try / catch

try {
    handleSaveMode();
} catch (PaimonConnectorException e) {
    if (e.getErrorCode() == UNSUPPORTED_BRANCH_SAVE_MODE && e.getMessage().contains("must exist")) {
        createMainTableThenRetry();
    } else throw e;
}

Prevention

When it happens

Trigger: sink with branch configured to a non-main branch while schema_save_mode/data_save_mode handling runs and catalog.tableExists(tablePath) is false — i.e. first-time write where the main table was never created.

Common situations: Creating the table implicitly via a sink write to a branch; dropped main table but branch config still set; typo in table path so existence check fails.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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