quickwit-oss/quickwit · error

`dynamic_mapping` is only allowed with mode=dynamic.

Error message

`dynamic_mapping` is only allowed with mode=dynamic. (here mode=`{:?}`)

What it means

Mode::from_parts rejects a config that sets a `dynamic_mapping` while `mode` is not `dynamic`. The dynamic_mapping options only have meaning in dynamic mode; pairing them with lenient or strict mode is treated as a configuration contradiction.

Solutions

  1. Remove the dynamic_mapping block if the intended mode is strict or lenient.
  2. Or set mode: dynamic if dynamic indexing options are actually desired.
  3. Update config-generation tooling to emit dynamic_mapping only for mode=dynamic.

Example fix

// before
mode: strict
dynamic_mapping:
  by_field_name:
    foo: {type: text}
// after
mode: strict
Defensive patterns

Strategy: validation

Validate before calling

if mode != "dynamic" && config.get("dynamic_mapping").is_some() {
    return Err("dynamic_mapping requires mode=dynamic".into());
}

Prevention

When it happens

Trigger: DocMapping config with `mode: strict` (or lenient) plus a `dynamic_mapping:` block, parsed via Mode::from_parts during index config deserialization/validation.

Common situations: Copy-pasted index configs where mode was switched to strict but dynamic_mapping options were left behind; tooling that always emits a dynamic_mapping default block regardless of mode.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/a4a6e8bf1ecfff0b. Report an issue: GitHub.

Appendix: source

Thrown at quickwit/quickwit-doc-mapper/src/doc_mapping.rs:69

    pub fn mode_type(&self) -> ModeType {
        match self {
            Self::Lenient => ModeType::Lenient,
            Self::Strict => ModeType::Strict,
            Self::Dynamic(_) => ModeType::Dynamic,
        }
    }

    /// Builds a [`Mode`] from its type and optional dynamic mapping options.
    pub fn from_parts(
        mode: ModeType,
        dynamic_mapping: Option<QuickwitJsonOptions>,
    ) -> anyhow::Result<Mode> {
        Ok(match (mode, dynamic_mapping) {
            (ModeType::Lenient, None) => Self::Lenient,
            (ModeType::Strict, None) => Self::Strict,
            (ModeType::Dynamic, Some(dynamic_mapping)) => Self::Dynamic(dynamic_mapping),
            (ModeType::Dynamic, None) => Self::default(), // Dynamic with default options
            (_, Some(_)) => anyhow::bail!(
                "`dynamic_mapping` is only allowed with mode=dynamic. (here mode=`{:?}`)",
                mode
            ),
        })
    }

    /// Obtains the mode type and dynamic options from a [`Mode`].
    pub fn into_parts(self) -> (ModeType, Option<QuickwitJsonOptions>) {
        match self {
            Self::Lenient => (ModeType::Lenient, None),
            Self::Strict => (ModeType::Strict, None),
            Self::Dynamic(json_options) => (ModeType::Dynamic, Some(json_options)),
        }
    }
}

impl Default for Mode {
    fn default() -> Self {

View on GitHub (pinned to a39730c5cd)