apache/seatunnel · error · IllegalArgumentException

Options 'credentials_path' and 'emulator_host' cannot be con

Error message

Options 'credentials_path' and 'emulator_host' cannot be configured together

What it means

GooglePubSubSinkConfig.from() validates that credentials_path and emulator_host are mutually exclusive. credentials_path selects real GCP service-account authentication while emulator_host targets a local Pub/Sub emulator; specifying both is ambiguous and rejected with IllegalArgumentException during config parsing.

Source

Thrown at seatunnel-connectors-v2/connector-google-pubsub/src/main/java/org/apache/seatunnel/connectors/seatunnel/google/pubsub/config/GooglePubSubSinkConfig.java:51

    private final String credentialsPath;
    private final String emulatorHost;
    private final MessageFormat format;
    private final String fieldDelimiter;

    public static GooglePubSubSinkConfig from(ReadonlyConfig config) {
        String projectId = config.get(GooglePubSubSinkOptions.PROJECT_ID);
        String topic = config.get(GooglePubSubSinkOptions.TOPIC);
        String credentialsPath = config.get(GooglePubSubSinkOptions.CREDENTIALS_PATH);
        String emulatorHost = config.get(GooglePubSubSinkOptions.EMULATOR_HOST);
        MessageFormat format = config.get(GooglePubSubSinkOptions.FORMAT);
        String fieldDelimiter = config.get(GooglePubSubSinkOptions.FIELD_DELIMITER);

        requireNonBlank(projectId, GooglePubSubSinkOptions.PROJECT_ID.key());
        requireNonBlank(topic, GooglePubSubSinkOptions.TOPIC.key());
        requireNonBlankIfPresent(credentialsPath, GooglePubSubSinkOptions.CREDENTIALS_PATH.key());
        requireNonBlankIfPresent(emulatorHost, GooglePubSubSinkOptions.EMULATOR_HOST.key());
        if (credentialsPath != null && emulatorHost != null) {
            throw new IllegalArgumentException(
                    "Options 'credentials_path' and 'emulator_host' cannot be configured together");
        }
        if (format == MessageFormat.TEXT && fieldDelimiter.isEmpty()) {
            throw new IllegalArgumentException("Option 'field_delimiter' cannot be empty");
        }

        return GooglePubSubSinkConfig.builder()
                .projectId(projectId)
                .topic(topic)
                .credentialsPath(credentialsPath)
                .emulatorHost(emulatorHost)
                .format(format)
                .fieldDelimiter(fieldDelimiter)
                .build();
    }

    private static void requireNonBlank(String value, String option) {
        if (value == null || value.trim().isEmpty()) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove emulator_host when running against real GCP, keeping only credentials_path.
  2. Remove credentials_path when targeting the local emulator.
  3. If both come from variables, make them conditionally exclusive in your config template (e.g. only emit emulator_host when EMULATOR is set).

Example fix

// before
credentials_path = "/path/sa.json"
emulator_host = "localhost:8085"
// after (real GCP)
credentials_path = "/path/sa.json"
// or (emulator)
emulator_host = "localhost:8085"
Defensive patterns

Strategy: validation

Validate before calling

// validate before building the sink config
boolean hasCreds = config.getString("credentials_path") != null;
boolean hasEmu = config.getString("emulator_host") != null;
if (hasCreds && hasEmu) throw new IllegalArgumentException("Set only one of credentials_path / emulator_host");

Try / catch

try {
  GooglePubSubSinkConfig.from(config);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("cannot be configured together")) {
    log.error("Remove either credentials_path or emulator_host from the sink config");
  } else throw e;
}

Prevention

When it happens

Trigger: A PubSub sink config contains non-null values for both credentials_path and emulator_host; from() is called when the sink is created, before any connection is made.

Common situations: Merging a production config (credentials_path) with a local-dev override (emulator_host) via environment variables or templating; leaving emulator_host set from a local test when deploying with real credentials.

Related errors


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