{"record":{"id":"e98efdf1cb4cd9fe","repo":"jdx/mise","slug":"setup-configuration-itself-cannot-be-encrypted-p","errorCode":null,"errorMessage":"setup configuration itself cannot be encrypted: {path}","messagePattern":"setup configuration itself cannot be encrypted: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/files.rs","lineNumber":255,"sourceCode":"        || inner.scheme != outer.scheme\n        || !layout::is_safe_branch_path(path)\n        || !matches!(inner.mode.as_str(), \"100644\" | \"100755\" | \"120000\")\n    {\n        bail!(\"encrypted file does not match its path or mode: {path}\");\n    }\n    Ok(())\n}\n\npub(crate) fn decrypt(\n    repo: &HistoryRepo,\n    path: &str,\n    object: &Object,\n    interactive: bool,\n) -> Result<Object> {\n    let outer = envelope(repo, object, agecrypt::MAX_ENCRYPTED_BYTES)?\n        .ok_or_else(|| eyre::eyre!(\"missing encrypted file envelope: {path}\"))?;\n    if control_file(path) {\n        bail!(\"setup configuration itself cannot be encrypted: {path}\");\n    }\n    if outer.path != path {\n        bail!(\"encrypted file does not match its path: {path}\");\n    }\n    if let Some(decrypted) = repo.decrypted_object(&object.1) {\n        return Ok(decrypted);\n    }\n    let bytes = agecrypt::decrypt_sync(&outer.ciphertext.0, interactive)\n        .wrap_err_with(|| format!(\"cannot unlock {path}; run mise bootstrap dotfiles pull interactively with a matching age identity\"))?;\n    let inner: Plaintext =\n        rmp_serde::from_slice(&bytes).wrap_err(\"invalid encrypted file payload\")?;\n    validate(path, &outer, &inner)?;\n    let oid = repo.transient_blob_id(&inner.content.0)?;\n    let decrypted = (inner.mode, oid);\n    repo.remember_decrypted(&object.1, decrypted.clone());\n    Ok(decrypted)\n}\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/sync/files.rs#L237-L273","documentation":"decrypt() refuses to decrypt any path that is itself a mise setup control/configuration file. Encryption is only meant for user dotfiles sourced from external locations; encrypting the setup's own configuration would create a circular dependency where mise cannot bootstrap itself. This guard fires before any decryption is attempted.","triggerScenarios":"Calling decrypt (via commit_object) with a path that control_file(path) classifies as setup configuration (e.g. mise's own config files inside the history store).","commonSituations":"A user added mise's setup config to the encrypted set in their dotfiles config; a glob/pattern over-broadly matches control files; migrating an old store where config files were wrongly encrypted.","solutions":["Remove the setup configuration path from the encrypted dotfile sources and keep it as plain tracked config.","Encrypt only external dotfile sources; store configuration unencrypted in the setup repository.","Rebuild the history store without the control file (fresh setup store) if it is already committed encrypted."],"exampleFix":"# before\n[[dotfiles]]\nsource = \"~/.config/mise/config.toml\"\nencrypt = true\n# after\n[[dotfiles]]\nsource = \"~/.config/mise/config.toml\"\nencrypt = false","handlingStrategy":"validation","validationCode":"if control_file(path) {\n    return Err(anyhow!(\"refusing to encrypt setup configuration: {path}\"));\n}","typeGuard":null,"tryCatchPattern":"match decrypt(repo, &object, path, interactive) {\n    Ok(obj) => obj,\n    Err(e) if e.to_string().starts_with(\"setup configuration itself cannot be encrypted\") => {\n        eprintln!(\"{path} is mise config; track it unencrypted\");\n        read_plain(path)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep mise setup config out of encrypted dotfile source globs.","Review glob patterns for over-broad matches before enabling encryption.","Audit which paths are encrypted after changing dotfile configuration."],"tags":["encryption","configuration","policy"],"backgroundTag":"unsupported-operation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}