{"record":{"id":"c9b3f241ccefe0ca","repo":"jdx/mise","slug":"conflicting-bootstrap-secret-declarations-for-name-first","errorCode":null,"errorMessage":"conflicting bootstrap secret declarations for {name}\n\n  first:\n    {}\n\n  second:\n    {}","messagePattern":"conflicting bootstrap secret declarations for (.+?)\n\n  first:\n    (.+?)\n\n  second:\n    (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/secrets.rs","lineNumber":101,"sourceCode":"}\n\n#[derive(Debug, thiserror::Error)]\n#[error(\n    \"required bootstrap secrets are unavailable: {details}. Supply them in the environment (for example, `fnox exec -- mise bootstrap ...`) or pass --prompt-secrets\"\n)]\nstruct SecretUnavailable {\n    details: String,\n}\n\npub(crate) fn declarations_from_config(config: &Config) -> Result<Vec<SecretDeclaration>> {\n    let mut merged: IndexMap<String, (SecretDeclaration, ResourceOrigin)> = IndexMap::new();\n    for config_files in config.bootstrap_config_maps() {\n        for (name, declaration) in secrets_from_config_files(config_files)? {\n            if let Some(existing) = merged.get(&name) {\n                if existing.0 == declaration.0 {\n                    continue;\n                }\n                bail!(\n                    \"conflicting bootstrap secret declarations for {name}\\n\\n  first:\\n    {}\\n\\n  second:\\n    {}\",\n                    existing.1.conflict_description(),\n                    declaration.1.conflict_description(),\n                );\n            }\n            merged.insert(name, declaration);\n        }\n    }\n    Ok(merged\n        .into_values()\n        .map(|(declaration, _)| declaration)\n        .collect())\n}\n\nfn secrets_from_config_files(\n    config_files: &ConfigMap,\n) -> Result<IndexMap<String, (SecretDeclaration, ResourceOrigin)>> {\n    let mut merged = IndexMap::new();","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/secrets.rs#L83-L119","documentation":"Bootstrap secrets are collected from every bootstrap config map and merged by name. If the same secret name is declared twice with different source definitions, mise cannot pick one, so it errors showing both conflicting declarations. Identical duplicates are silently accepted.","triggerScenarios":"Calling statuses() or resolve() (during `mise bootstrap` operations) when two loaded config files both declare a secret with the same name but different env/description/allow_empty settings.","commonSituations":"A global mise.toml and a project mise.toml both define [bootstrap.secret.API_KEY] with different env var names, or an included config redefines an existing secret with tweaked options after copying a template.","solutions":["Remove or rename the duplicate declaration in one of the config files","Make the declarations identical (same env, description, allow_empty) so they merge cleanly","Use `mise bootstrap plan` / inspect loaded config files to find which two files declare the secret"],"exampleFix":"# before — global mise.toml\n[bootstrap.secrets.API_KEY]\nenv = \"GLOBAL_API_KEY\"\n# project mise.toml\n[bootstrap.secrets.API_KEY]\nenv = \"PROJECT_API_KEY\"\n# after\n[bootstrap.secrets.API_KEY]\nenv = \"PROJECT_API_KEY\"","handlingStrategy":"validation","validationCode":"// before apply, detect duplicate secret names across loaded configs\nlet mut seen: HashMap<&str, &str> = HashMap::new();\nfor (file, decls) in all_bootstrap_config_maps() {\n    for (name, d) in decls {\n        if let Some(prev) = seen.insert(name, file) {\n            eprintln!(\"duplicate secret {name} in {prev} and {file}\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"conflicting bootstrap secret declarations\") => {\n        eprintln!(\"{}\", e); // message embeds both declarations\n        // inspect the listed config files and deduplicate\n    }\n    other => other?,\n}","preventionTips":["Keep each secret declared in exactly one config layer","When including/copying config templates, strip duplicated [bootstrap.secrets] tables","Use `mise bootstrap plan` to review merged secret declarations before apply"],"tags":["config","secrets","conflict","bootstrap"],"backgroundTag":"conflicting-config-options","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}