{"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).wrap_err_with(|| {\n        format!(\n            \"cannot unlock {path}; run mise dot pull interactively with a matching age identity\"\n        )\n    })?;\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());","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/sync/files.rs#L237-L273","documentation":"This error is thrown by `decrypt` in the history-sync files module when an attempt is made to decrypt a file that is itself part of the sync's setup configuration (control files, e.g. config/metadata tracked by the sync system). Encrypting or decrypting these control files would corrupt the synchronization machinery, so they are explicitly rejected. It is a policy guard, not a data corruption.","triggerScenarios":"Calling `decrypt` (via `commit_object`) on a path for which `control_file(path)` returns true — i.e. the user added the sync setup configuration file itself as an encrypted dotfile.","commonSituations":"A user adds their entire dotfiles directory to sync encryption, sweeping in the setup store's own config file (e.g. sync configuration inside ~/.config that is also the control file); overly broad glob patterns in encrypted-file lists.","solutions":["Remove the control/setup configuration file from the set of paths being encrypted.","Narrow the encryption path list/glob so it only includes external dotfiles, not the sync configuration.","Move the setup configuration outside the encrypted source directory if both must coexist."],"exampleFix":"// before (sync config listing)\nencrypt = [\"~/.config/**\"]\n// after\nencrypt = [\"~/.config/nvim/**\", \"~/.config/git/**\"] // exclude the sync control file itself","handlingStrategy":"validation","validationCode":"// skip files that are sync control files\nif (isControlFile(path)) continue; // or surface a clear message to the user\nawait sync.decrypt(path);","typeGuard":"function isEncryptable(path: string): boolean {\n  return !isControlFile(path);\n}","tryCatchPattern":"try {\n  await sync.decrypt(path);\n} catch (e) {\n  if (isControlFile(path)) log.warn(`skipping control file: ${path}`);\n  else throw e;\n}","preventionTips":["Exclude the sync configuration path from every encryption glob.","Use negation patterns for control files in include lists.","Keep sync config in a directory outside the encrypted source root."],"tags":["encryption","configuration","validation"],"backgroundTag":"invalid-config-value","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"}