{"record":{"id":"213fb4915cd73200","repo":"sxyazi/yazi","slug":"invalid-file-mode-value-04o","errorCode":null,"errorMessage":"invalid file mode: {value:04o}","messagePattern":"invalid file mode: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/cha/mode.rs","lineNumber":66,"sourceCode":"\tfn deref(&self) -> &Self::Target {\n\t\tmatch *self & Self::T_MASK {\n\t\t\tSelf::T_FILE => &ChaType::File,\n\t\t\tSelf::T_DIR => &ChaType::Dir,\n\t\t\tSelf::T_LINK => &ChaType::Link,\n\t\t\tSelf::T_BLOCK => &ChaType::Block,\n\t\t\tSelf::T_CHAR => &ChaType::Char,\n\t\t\tSelf::T_SOCK => &ChaType::Sock,\n\t\t\tSelf::T_FIFO => &ChaType::FIFO,\n\t\t\t_ => &ChaType::Unknown,\n\t\t}\n\t}\n}\n\nimpl TryFrom<u16> for ChaMode {\n\ttype Error = anyhow::Error;\n\n\tfn try_from(value: u16) -> Result<Self, Self::Error> {\n\t\tlet me = Self::from_bits(value).ok_or_else(|| anyhow!(\"invalid file mode: {value:04o}\"))?;\n\t\tmatch me & Self::T_MASK {\n\t\t\tSelf::T_FILE\n\t\t\t| Self::T_DIR\n\t\t\t| Self::T_LINK\n\t\t\t| Self::T_BLOCK\n\t\t\t| Self::T_CHAR\n\t\t\t| Self::T_SOCK\n\t\t\t| Self::T_FIFO => Ok(me),\n\t\t\t_ => bail!(\"invalid file type: {value:04o}\"),\n\t\t}\n\t}\n}\n\n#[cfg(unix)]\nimpl From<ChaMode> for std::fs::Permissions {\n\tfn from(value: ChaMode) -> Self {\n\t\tuse std::os::unix::fs::PermissionsExt;\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/cha/mode.rs#L48-L84","documentation":"ChaMode is a bitflags type over the file-type portion of the Unix st_mode (T_FILE, T_DIR, T_LINK, T_BLOCK, T_CHAR, T_SOCK, T_FIFO). TryFrom<u16> first round-trips the value through from_bits — \"invalid file mode\" means the u16 contains bits outside the defined ChaMode flags — and then requires the type bits (T_MASK) to match exactly one known type, bailing \"invalid file type\" otherwise.","triggerScenarios":"Passing a full st_mode that includes permission bits not modeled in ChaMode's flag set, or a permission-only value like 0o644 whose type bits are zero, leaving the T_MASK match with no valid variant.","commonSituations":"Code or plugins building Cha by hand from libc stat output; test fixtures with arbitrary modes; platform mode values containing bits (sticky/setuid) absent from the bitflags definition.","solutions":["Extract the type bits before converting: pass (st_mode & 0o170000) as u16 (S_IFMT mask)","If only permissions are available, OR in an explicit type: 0o100000 | perms for a regular file","If a legitimate platform bit is rejected, extend the ChaMode bitflags definition to cover it"],"exampleFix":"// before: full st_mode, permission bits rejected by from_bits\nlet mode = ChaMode::try_from(st.st_mode as u16)?;\n\n// after: type bits only (S_IFMT)\nlet mode = ChaMode::try_from((st.st_mode & 0o170000) as u16)?;","handlingStrategy":"type-guard","validationCode":"// Extract only the type bits (S_IFMT) before converting:\nconst S_IFMT: u16 = 0o170000;\nlet mode = ChaMode::try_from(st.st_mode & S_IFMT as u32 as u16)?;","typeGuard":"const S_IFMT: u16 = 0o170000;\nfn is_valid_file_mode(value: u16) -> bool {\n    matches!(\n        value & S_IFMT,\n        0o100000 | 0o040000 | 0o120000 | 0o060000 | 0o020000 | 0o140000 | 0o010000\n    )\n}","tryCatchPattern":"match ChaMode::try_from(raw) {\n    Ok(m) => m,\n    Err(e) if e.to_string().starts_with(\"invalid file mode\") => ChaMode::try_from(raw & 0o170000)?,\n    Err(e) => return Err(e),\n}","preventionTips":["Always mask with S_IFMT (0o170000) before TryFrom<u16>","Never feed a full st_mode including permission bits","Unit-test the conversion for every file type you support"],"tags":["fs","file-mode","bitflags","stat","unix"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}