{"record":{"id":"1acc01a04f27b90d","repo":"LGUG2Z/komorebi","slug":"custom-layouts-must-be-json-or-yaml-files","errorCode":null,"errorMessage":"custom layouts must be json or yaml files","messagePattern":"custom layouts must be json or yaml files","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"komorebi-layouts/src/custom_layout.rs","lineNumber":42,"sourceCode":"}\n\nimpl DerefMut for CustomLayout {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\nimpl CustomLayout {\n    pub fn from_path<P: AsRef<Path>>(path: P) -> eyre::Result<Self> {\n        let path = path.as_ref();\n        let layout: Self = match path.extension() {\n            Some(extension) if extension == \"yaml\" || extension == \"yml\" => {\n                serde_json::from_reader(BufReader::new(File::open(path)?))?\n            }\n            Some(extension) if extension == \"json\" => {\n                serde_json::from_reader(BufReader::new(File::open(path)?))?\n            }\n            _ => bail!(\"custom layouts must be json or yaml files\"),\n        };\n\n        if !layout.is_valid() {\n            bail!(\"the layout file provided was invalid\");\n        }\n\n        Ok(layout)\n    }\n\n    #[must_use]\n    pub fn column_with_idx(&self, idx: usize) -> (usize, Option<&Column>) {\n        let column_idx = self.column_for_container_idx(idx);\n        let column = self.get(column_idx);\n        (column_idx, column)\n    }\n\n    #[must_use]\n    pub fn primary_idx(&self) -> Option<usize> {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/LGUG2Z/komorebi/blob/e0709f02bfae4e503bf4640f58ee75ecbbfdbb97/komorebi-layouts/src/custom_layout.rs#L24-L60","documentation":"CustomLayout::from_path loads a user-defined layout and only accepts .json, .yaml, or .yml extensions. Any other extension (or none) reaches the bail! arm with this message, aborting with an eyre error.","triggerScenarios":"Calling CustomLayout::from_path with a file whose extension is not json/yaml/yml, e.g. my_layout.txt, layout, or layout.json5. Referenced via komorebic --layout or static/dynamic layout config.","commonSituations":"Saving a downloaded layout without its extension; using .yason/.toml; text editor appending .txt; pointing --layout at documentation instead of the actual layout file.","solutions":["Rename the layout file to end with .json (or .yaml/.yml).","Confirm the path passed via --layout or custom_layouts config points at the correct file.","If the layout is in another format, convert it to JSON first."],"exampleFix":"// before\nkomorebic --layout ultrawide.txt\n// after\nkomorebic --layout ultrawide.json","handlingStrategy":"validation","validationCode":"let ext = std::path::Path::new(layout_path)\n    .extension()\n    .map(|e| e.to_string_lossy().to_lowercase());\nassert!(matches!(ext.as_deref(), Some(\"json\") | Some(\"yaml\") | Some(\"yml\")), \"layout must be json or yaml\");","typeGuard":"fn is_supported_layout(path: &std::path::Path) -> bool {\n    path.extension().map(|e| {\n        matches!(e.to_string_lossy().to_lowercase().as_str(), \"json\" | \"yaml\" | \"yml\")\n    }).unwrap_or(false)\n}","tryCatchPattern":"match CustomLayout::from_path(&path) {\n    Ok(l) => l,\n    Err(e) => eprintln!(\"layout load failed: {e}; use .json/.yaml/.yml\"),\n}","preventionTips":["Name custom layout files with .json/.yml extensions","Check the --layout argument points at a real file with a supported extension","Convert TOML/TXT layouts before use"],"tags":["layout","file-extension","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"e0709f02bfae4e503bf4640f58ee75ecbbfdbb97","analyzedAt":"2026-09-06T07:08:05.107Z","contentChangedAt":"2026-09-06T07:08:05.107Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}