ErrLookup › Background articles › Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries
Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries
"Conflicting config options" errors — messages like "env and jsc.target cannot be used together", "must be provided together", or "only supported for" — appear when a library's config validation rejects mutually contradictory or ambiguous option combinations. Developers hit them at startup, build, or DDL time when one setting disables or contradicts another.
Distilled from 1,160 documented records across 162 repositories.
Background
This family covers failures produced not by bad input data at runtime but by a configuration or registration layer that refuses to proceed because the declared options are mutually contradictory, ambiguous, or incomplete. The check usually runs in a dedicated validation step: swc rejects options where both env (preset-env-style transforms) and jsc.target are set, because both drive how far output is downgraded and the target becomes ambiguous; SeaTunnel's JsonDeserializationSchema throws SeaTunnelJsonFormatException with ILLEGAL_ARGUMENT when failOnMissingField (strict failure) and ignoreParseErrors (silent tolerance) are both enabled; RisingWave's Iceberg sink validation rejects enable_pk_index set on a non-upsert sink, because a per-key index only makes sense where rows are overwritten; dbt-core's dbt_runtime macro rejects start_paused with a multi_thread flavor at compile time because paused time only exists on the current_thread runtime; Druid's Kubernetes task runner refuses any pod adapter other than multiContainer when sidecarSupport is enabled; and Quickwit's node validation only allows the compactor service when enable_standalone_compactors is true.
The layer that produces these errors varies by library, but the shape is consistent: a builder, macro, schema parser, registrar, or validate() function inspects the fully assembled option set and fails fast before doing real work. JVM libraries typically throw IllegalArgumentException (133 of the family's records) or ConfigurationException (93), with IllegalStateException (61) where reuse consistency is violated, as in Aeron's rejection of a spies-simulate-connection value that differs from the existing publication on the same channel. Python libraries raise ValueError (54); Rust libraries surface anyhow::Error (21) or compile-time syn::Error from proc macros, as in dbt-core and pydantic/monty, where contradictory attributes are rejected at macro-expansion time before the program ever runs. Across the corpus the dominant handling strategy is validation (1087 of 1160 records), meaning the library deliberately checks and refuses rather than silently picking one interpretation.
Two sub-families are worth distinguishing. The first is true mutual exclusion: two options that each make sense alone but contradict each other, such as swc's env vs jsc.target, SeaTunnel's two JSON error policies, Chroma's rejection of creating a collection with both hnsw and spann index configurations, or shadowsocks-rust requiring that server, server_port, method, and password in a per-server entry be provided together or not at all. The second is option-dependency or context-scoping: an option is only meaningful in a specific mode or context, such as RisingWave's upsert-only enable_pk_index, Dropwizard requiring all parameters of a resource method to use the same validation groups, MassTransit allowing AddMassTransit() only once per container, or Spring Security refusing to auto-create an OAuth2AuthorizedClientManager when multiple OAuth2AuthorizedClientProvider beans exist. Related but distinct is the reuse-consistency variant, where the conflict is not within one config file but between a new request and already-registered state — Aeron's per-stream flags, COLA's duplicate extension registration for the same coordinate, and aspnetboilerplate's rejection of two localization dictionaries for the same culture all work this way.
From the caller's side these errors usually appear at the worst possible moment: application startup, kernel restart, container registration, macro expansion, or DDL submission — the library fails fast by design so that an ambiguous configuration never produces silently wrong behavior. Severities in the family are overwhelmingly recorded as error (1009 of 1160), with a minority of warnings (99), critical (38), and info (14). Messages are typically explicit about which options conflict and often name the allowed combination — the Spinnaker GCE deploy handler, for instance, states that accelerators are only supported with regional server groups if the zones are specified by the user. Because the library cannot guess intent, the fix is almost always on the configuration side: pick one of the alternatives, add the required companion option, or align values that must match across a registration.
Common causes
- Two mutually exclusive options both enabled. The most common pattern: options that each work alone contradict when combined. Examples include swc's env block alongside jsc.target, SeaTunnel's failOnMissingField and ignoreParseErrors both true, and Chroma collections configured with both hnsw and spann index blocks.
- Option used outside its supported mode or context. A flag only valid in one mode is set in another: enable_pk_index on a non-upsert RisingWave iceberg sink, start_paused with a multi_thread flavor in dbt-core's runtime macro, an endDate supplied without timeDuration when rescheduling a Flowable timer, or a non-multiContainer pod adapter with Druid's sidecarSupport enabled.
- Partial or incomplete option sets that must go together. Some options form an all-or-nothing group. shadowsocks-rust rejects per-server entries where only some of server, server_port, method, and password are present, because a partial combination is structurally ambiguous.
- Duplicate registration of the same identity. Registering the same key, type, or coordinate twice creates ambiguity rather than a literal option clash. MassTransit rejects a second AddMassTransit() call per container, COLA rejects duplicate @Extension registrations for the same coordinate, aspnetboilerplate rejects two dictionaries for one culture in a localization source, and Stride's ViewModelServiceProvider refuses a service type matching multiple registrations.
- Inconsistent values across shared or reused state. A new request conflicts with already-registered configuration. Aeron rejects a spies-simulate-connection setting that differs from the existing publication on the same channel, since the flag must be consistent across reuse of the same log buffer.
- Intra-method or intra-block inconsistency. Options must be uniform within a scope: Dropwizard throws when parameters of a single resource method declare different bean-validation groups, because the validator can only apply one group set per request.
- Multiple auto-detected candidates where exactly one is required. Spring Security refuses to auto-create an OAuth2AuthorizedClientManager when multiple OAuth2AuthorizedClientProvider beans are in the context alongside a custom authorized-client-provider-ref; the registrar needs exactly one provider to infer intent.
What usually fixes it
- Pick one option of the mutually exclusive pair: remove or disable the other (delete jsc.target and use env.targets, or drop the env block; set exactly one of failOnMissingField / ignoreParseErrors; keep only hnsw or spann).
- Align the option with the mode that supports it: switch the sink type to upsert for enable_pk_index, use flavor = current_thread for start_paused, or set the required companion flag such as enable_standalone_compactors for the Quickwit compactor service.
- Supply or remove complete option groups: give shadowsocks all four server fields or none, and null out dependent fields like Flowable's endDate when switching schedule modes.
- De-duplicate registrations: remove the second AddMassTransit() call (or use the documented typed-bus pattern), give colliding @Extension coordinates distinct identities, and make each localization culture appear exactly once per source.
- Audit layered configuration sources — config files, CLI flags, framework-injected defaults, environment overrides — and log or print the fully merged options to find which layer injects the conflicting value.
- Add a validation or lint step (CI check, schema lint, config check command) that rejects contradictory combinations before deployment, since these errors are designed to fail fast at startup or build time.
Documented occurrences
- Unable to create an %s bean. Expected one bean of type %s, but found multiple. Please consider defining only a single bean of this type, or define an %s bean yourself. (spring-projects/spring-security)
- The beam_sql magic tries to query PCollections from multiple pipelines: %s and %s (apache/beam)
- Unable to determine whether certain files are orphan. Found in filesystem: {} and in table: {} (apache/iceberg)
- expo-app-intents is already configured to use the '${configuredDirectory}' directory, and this run would point it at '${directory}' instead. Only init can decide to move the plugin; it cannot decide whether '${configuredDirectory}' still holds Swift files you need, so it would stay in experiments.inlineModules.watchedDirectories. Both directories would then hold an AppIntentsSetup.swift, autolinking compiles every watched directory into the app target, and the iOS build fails with `error: filename "AppIntentsSetup.swift" used twice`. Run `npx expo-app-intents init --dir ${configuredDirectory}` to keep the current layout. To move to '${directory}', move the Swift files there yourself, then stop autolinking from scanning '${configuredDirectory}': it is covered by ${isSingleEntry ? 'the entry' : 'the entries'} ${entryList} in experiments.inlineModules.watchedDirectories, so delete ${isSingleEntry ? 'that entry' : 'those entries'} or narrow ${isSingleEntry ? 'it' : 'them'} to a directory that does not contain '${configuredDirectory}'. Then re-run this command. (expo/expo)
- The `start_paused` option requires the `current_thread` runtime flavor. Use `#[{macro_name}(flavor = "current_thread")]` (dbt-labs/dbt-core)
- `enable_pk_index` is only supported for upsert iceberg sink (risingwavelabs/risingwave)
- `kwargs_not_supported_yet` cannot be combined with `kwarg_error_name` — the override only applies to the unknown-kwarg dispatch path, which is skipped (pydantic/monty)
- `server`, `server_port`, `method`, `password` must be provided together (shadowsocks/shadowsocks-rust)
- Cannot specify both 'hnsw' and 'spann' configurations during creation. (chroma-core/chroma)
- capsule '{}' changed while activation was in progress (astrid-runtime/astrid)
- OIDC configuration changed during validation (siyuan-note/siyuan)
- Cannot mix IF conditions and %s for the same row (apache/cassandra)
- missingFixedModifier: missingFixedModifier (apple/pkl)
- An end date can only be provided when rescheduling a timer using timeDuration. (flowable/flowable-engine)
- EXTENSION_DEFINE_DUPLICATE: Duplicate registration is not allowed for :${extensionCoordinate} (alibaba/COLA)
- Parameters must have the same validation groups in %s (dropwizard/dropwizard)
- ILLEGAL_ARGUMENT: JSON format doesn't support failOnMissingField and ignoreParseErrors are both enabled. (apache/seatunnel)
- Invalid pod adapter [%s], only pod adapter [%s] can be specified when sidecarSupport is enabled (apache/druid)
- APPEND + TRUNCATE not allowed (MuntashirAkon/AppManager)
- the `compactor` service can only be enabled when `enable_standalone_compactors` is true (or `QW_ENABLE_STANDALONE_COMPACTORS=true`). With the default indexer-local merge pipeline, the compactor service must not be enabled. (quickwit-oss/quickwit)
…and 1,140 more across the corpus — use search.
Honest provenance: generated on 2026-09-14 from AI-assisted analysis of the linked records. See how records are made.