apache/seatunnel · error · IllegalArgumentException

GcsFile path must point to a prefix below the bucket root wh

Error message

GcsFile path must point to a prefix below the bucket root when schema_save_mode is %s or data_save_mode is %s

What it means

When schema_save_mode or data_save_mode is a destructive mode (e.g. DELETE_DATA / overwrite-style cleanup), GcsFileSinkFactory validates that the configured file path is a real prefix below the bucket root. A path that normalizes to empty or "/" would make the destructive mode wipe the whole bucket, so it throws IllegalArgumentException.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-gcs/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/gcs/sink/GcsFileSinkFactory.java:151

            createSink(TableSinkFactoryContext context) {
        ReadonlyConfig readonlyConfig = context.getOptions();
        validateDestructivePath(readonlyConfig);
        CatalogTable catalogTable = context.getCatalogTable();
        return () -> new GcsFileSink(readonlyConfig, catalogTable);
    }

    private static void validateDestructivePath(ReadonlyConfig readonlyConfig) {
        SchemaSaveMode schemaSaveMode = readonlyConfig.get(FileBaseSinkOptions.SCHEMA_SAVE_MODE);
        DataSaveMode dataSaveMode = readonlyConfig.get(FileBaseSinkOptions.DATA_SAVE_MODE);
        if (schemaSaveMode != SchemaSaveMode.RECREATE_SCHEMA
                && dataSaveMode != DataSaveMode.DROP_DATA) {
            return;
        }

        String filePath = readonlyConfig.get(FileBaseSinkOptions.FILE_PATH);
        String normalizedPath = new Path(filePath).toUri().normalize().getPath();
        if (normalizedPath == null || normalizedPath.isEmpty() || "/".equals(normalizedPath)) {
            throw new IllegalArgumentException(
                    String.format(
                            "GcsFile path must point to a prefix below the bucket root when "
                                    + "schema_save_mode is %s or data_save_mode is %s",
                            schemaSaveMode, dataSaveMode));
        }
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set file_path to a concrete prefix under the bucket, e.g. file_path = "gs://mybucket/output/data"
  2. If bucket-root writes are intended, change schema_save_mode/data_save_mode to non-destructive values (e.g. CREATE_SCHEMA_WHEN_NOT_EXIST / APPEND)
  3. Ensure any template variables used in file_path actually resolve to non-empty values

Example fix

// before
file_path = "gs://mybucket/"          // root path + destructive save mode
schema_save_mode = "DELETE_SCHEMA"
// after
file_path = "gs://mybucket/output/2026-09-10"
schema_save_mode = "DELETE_SCHEMA"
Defensive patterns

Strategy: validation

Validate before calling

// Java: validate destructive-mode path before job submission
String filePath = config.get("file_path");
String normalized = new Path(filePath).toUri().normalize().getPath();
String schemaMode = config.get("schema_save_mode");
String dataMode = config.get("data_save_mode");
boolean destructive = "DELETE_SCHEMA".equals(schemaMode) || "DELETE_DATA".equals(dataMode);
if (destructive && (normalized == null || normalized.isEmpty() || "/".equals(normalized))) {
    throw new IllegalArgumentException("Destructive save mode requires a prefix below bucket root");
}

Try / catch

try {
    factory.createSink(...);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("prefix below the bucket root")) {
        logger.error("Set file_path to a concrete prefix (not bucket root) or use non-destructive save modes");
    }
    throw e;
}

Prevention

When it happens

Trigger: createSink → validateDestructivePath: FILE_PATH normalizes to "/" or empty (e.g. file_path = "/" or "gs://bucket/" with no prefix) while a destructive save mode is selected.

Common situations: User set file_path = "gs://mybucket/" intending to write at bucket root while using DELETE_DATA save mode; templated path variable resolved to empty leaving just the bucket; copy-pasted example config with root path kept in place.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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