{"record":{"id":"d6e1b885e102c805","repo":"quickwit-oss/quickwit","slug":"document-clustering-policies-must-contain-at-least","errorCode":null,"errorMessage":"document clustering policies must contain at least one policy","messagePattern":"document clustering policies must contain at least one policy","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-config/src/docs_clustering.rs","lineNumber":97,"sourceCode":"            return Ok(None);\n        };\n\n        match disable_override {\n            Some(true) => Ok(None),\n            Some(false) | None => {\n                let config = DocsClusteringConfig {\n                    policies: config_builder.policies,\n                };\n                config.validate()?;\n                Ok(Some(config))\n            }\n        }\n    }\n}\n\nimpl DocsClusteringConfig {\n    pub fn validate(&self) -> anyhow::Result<()> {\n        ensure!(\n            !self.policies.is_empty(),\n            \"document clustering policies must contain at least one policy\"\n        );\n        for policy in &self.policies {\n            policy.validate()?;\n        }\n        Ok(())\n    }\n}\n\n/// Defines how documents are clustered.\n#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]\n#[serde(deny_unknown_fields, untagged)]\npub enum ClusteringPolicy {\n    /// Clusters documents using structure and configured field fingerprints.\n    Fingerprint { fingerprint: FingerprintPolicy },\n}\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-config/src/docs_clustering.rs#L79-L115","documentation":"DocsClusteringConfig::validate enforces that a `doc_clustering` (docs mapping) configuration contains at least one clustering policy. An empty `policies` list is a useless clustering configuration, so validation rejects it with this message.","triggerScenarios":"Defining an index config with `doc_clustering.policies: []` (or the key present but YAML/JSON yields an empty array), then calling the config builder's validate/build path (via `build_optional`) or index creation.","commonSituations":"Copy-pasting a clustering config template and removing all policies; programmatically generating config where a filter produced an empty list; commenting out all policy blocks but leaving the empty key.","solutions":["Add at least one policy under `doc_clustering.policies` (e.g. a fingerprint policy with fields).","If clustering is not needed, remove the whole `doc_clustering` section instead of leaving an empty policies list.","Run the config validation (`quickwit index create` dry run or the validate path) locally before deploying to catch this early."],"exampleFix":"# before\ndoc_clustering:\n  policies: []\n# after\ndoc_clustering:\n  policies:\n    - fingerprint:\n        - field: level\n          method: exact","handlingStrategy":"validation","validationCode":"const policies = config.doc_clustering?.policies ?? [];\nif (policies.length === 0) {\n  throw new Error('doc_clustering.policies must contain at least one policy');\n}","typeGuard":"const hasPolicies = (c) => Array.isArray(c?.doc_clustering?.policies) && c.doc_clustering.policies.length > 0;","tryCatchPattern":"try {\n  const index = await qw.createIndex(config);\n} catch (e) {\n  if (String(e).includes('document clustering policies must contain at least one policy')) {\n    // fix config: add a policy or drop the doc_clustering section\n  } else throw e;\n}","preventionTips":["Remove the entire doc_clustering section when clustering is not used, instead of leaving an empty policies array.","Lint index configs to reject empty arrays under doc_clustering.policies before submission.","When generating config programmatically, fail fast if a filter yields zero policies."],"tags":["config","validation","clustering"],"backgroundTag":"empty-required-field","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}