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
- Keep only credentials_path for real GCP usage and delete emulator_host.
- Keep only emulator_host when developing against the Pub/Sub emulator and remove credentials_path.
- 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
- Separate emulator-based dev configs from production configs entirely.
- Use profile-based templates so credentials_path and emulator_host never coexist.
- Review inherited/shared config fragments before merging them into a source config.
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
- Option 'field_delimiter' cannot be empty
- Option 'batch_size' must be between 1 and 32
- Option 'visibility_timeout_seconds' must be between 1 and 60
- Option 'poll_interval_ms' must be greater than zero
- Option 'max_in_flight_messages' must be greater than or equa
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b0ca0486c65fb5ae.
Report an issue: GitHub.