{"record":{"id":"62a2b82db8d00af1","repo":"jdx/mise","slug":"unsupported-encrypted-file-mode-path","errorCode":null,"errorMessage":"unsupported encrypted file mode: {path}","messagePattern":"unsupported encrypted file mode: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/files.rs","lineNumber":342,"sourceCode":"        })\n        .collect::<Result<Vec<_>>>()?;\n    encrypt(repo, path, object, &scheme, &recipients)\n}\n\n/// Encrypt bytes before they enter Git. Callers may store only the returned\n/// envelope, never the input or the decrypted payload in repository objects.\npub(crate) fn encode(\n    path: &str,\n    mode: &str,\n    content: &[u8],\n    scheme: &str,\n    recipients: &[Box<dyn age::Recipient + Send>],\n) -> Result<Vec<u8>> {\n    if control_file(path) {\n        bail!(\"encrypt an external dotfile source instead of configuration: {path}\");\n    }\n    if !matches!(mode, \"100644\" | \"100755\" | \"120000\") {\n        bail!(\"unsupported encrypted file mode: {path}\");\n    }\n    let inner = Plaintext {\n        path: path.into(),\n        mode: mode.into(),\n        scheme: scheme.into(),\n        content: Bytes(content.to_vec()),\n    };\n    let bytes = rmp_serde::to_vec_named(&inner)?;\n    let outer = Envelope {\n        path: path.into(),\n        mode: mode.into(),\n        scheme: scheme.into(),\n        ciphertext: Bytes(agecrypt::encrypt_bytes(&bytes, recipients)?),\n    };\n    let mut encoded = MAGIC.to_vec();\n    encoded.extend(rmp_serde::to_vec_named(&outer)?);\n    if encoded.len() as u64 > agecrypt::MAX_ENCRYPTED_BYTES {\n        bail!(\"encrypted file exceeds the size limit: {path}\");","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/sync/files.rs#L324-L360","documentation":"encode() only supports git file modes 100644 (regular), 100755 (executable), and 120000 (symlink) for encrypted files. Any other mode string — directories, submodules, setuid bits, or malformed mode values — is rejected before building the plaintext envelope.","triggerScenarios":"Calling encrypt()/encode() with a mode string other than \"100644\" | \"100755\" | \"120000\" (e.g. \"040755\" for a directory, \"160000\" for a submodule, or an arbitrary string).","commonSituations":"Trying to encrypt a directory or git submodule; filesystems reporting unusual permission bits; a config that lets users set a mode manually and contains a typo.","solutions":["Encrypt individual regular files (or symlinks) instead of directories or submodules.","Normalize the file's permissions to 0644 or 0755 before syncing.","Fix the mode value in the source config to a supported git mode."],"exampleFix":"// before\nencrypt_file(path, \"160000\", content, scheme, recipients)\n// after\nencrypt_file(path, \"100644\", content, scheme, recipients)","handlingStrategy":"validation","validationCode":"const SUPPORTED: [&str; 3] = [\"100644\", \"100755\", \"120000\"];\nif !SUPPORTED.contains(&mode) {\n    return Err(anyhow!(\"unsupported mode {mode} for {path}\"));\n}","typeGuard":null,"tryCatchPattern":"match encrypt(path, mode, content, scheme, recipients) {\n    Ok(bytes) => Ok(bytes),\n    Err(e) if e.to_string().contains(\"unsupported encrypted file mode\") => {\n        eprintln!(\"skipping {path}: not a regular file/symlink\");\n        Ok(())\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Only register files (not directories or submodules) in encrypted sources.","Normalize permissions to 0644/0755 before syncing.","Validate mode strings against 100644|100755|120000 at config load time."],"tags":["encryption","git-mode","validation"],"backgroundTag":"invalid-enum-value","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"}