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

GooglePubSubSourceConfig.from() applies the same validation as the sink config: credentials_path (service-account auth) and emulator_host (local emulator) are mutually exclusive, and specifying both throws IllegalArgumentException at source creation. The source variant uses GooglePubSubSourceOptions keys.

Source

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

    public static GooglePubSubSourceConfig from(ReadonlyConfig config) {
        String projectId = config.get(GooglePubSubSourceOptions.PROJECT_ID);
        String subscription = config.get(GooglePubSubSourceOptions.SUBSCRIPTION);
        String credentialsPath = config.get(GooglePubSubSourceOptions.CREDENTIALS_PATH);
        String emulatorHost = config.get(GooglePubSubSourceOptions.EMULATOR_HOST);
        MessageFormat format = config.get(GooglePubSubSourceOptions.FORMAT);
        String fieldDelimiter = config.get(GooglePubSubSourceOptions.FIELD_DELIMITER);
        Long maxOutstandingMessages =
                config.get(GooglePubSubSourceOptions.MAX_OUTSTANDING_MESSAGES);
        Long maxOutstandingBytes = config.get(GooglePubSubSourceOptions.MAX_OUTSTANDING_BYTES);
        Integer parallelPullCount = config.get(GooglePubSubSourceOptions.PARALLEL_PULL_COUNT);

        requireNonBlank(projectId, GooglePubSubSourceOptions.PROJECT_ID.key());
        requireNonBlank(subscription, GooglePubSubSourceOptions.SUBSCRIPTION.key());
        requireNonBlankIfPresent(credentialsPath, GooglePubSubSourceOptions.CREDENTIALS_PATH.key());
        requireNonBlankIfPresent(emulatorHost, GooglePubSubSourceOptions.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");
        }
        requirePositive(
                maxOutstandingMessages, GooglePubSubSourceOptions.MAX_OUTSTANDING_MESSAGES.key());
        requirePositive(maxOutstandingBytes, GooglePubSubSourceOptions.MAX_OUTSTANDING_BYTES.key());
        requirePositive(parallelPullCount, GooglePubSubSourceOptions.PARALLEL_PULL_COUNT.key());

        return GooglePubSubSourceConfig.builder()
                .projectId(projectId)
                .subscription(subscription)
                .credentialsPath(credentialsPath)
                .emulatorHost(emulatorHost)
                .format(format)
                .fieldDelimiter(fieldDelimiter)
                .maxOutstandingMessages(maxOutstandingMessages)

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Keep only credentials_path for real GCP usage and delete emulator_host.
  2. Keep only emulator_host when developing against the Pub/Sub emulator and remove credentials_path.
  3. Make your config templating emit one or the other based on environment.

Example fix

// before
source {
  GooglePubSub {
    credentials_path = "/path/sa.json"
    emulator_host = "localhost:8085"
  }
}
// after
source {
  GooglePubSub {
    credentials_path = "/path/sa.json"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// before building the source 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 {
  GooglePubSubSourceConfig.from(config);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("cannot be configured together")) {
    log.error("Source config: remove either credentials_path or emulator_host");
  } else throw e;
}

Prevention

When it happens

Trigger: A PubSub source config sets both credentials_path and emulator_host to non-null values; from() runs when the source reader is created, before connecting to Pub/Sub.

Common situations: Shared base config carrying credentials_path while a dev profile adds emulator_host; inheriting emulator_host from a local-test template when deploying with real service accounts.

Related errors


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