{"record":{"id":"4860972002122e8a","repo":"sinelaw/fresh","slug":"buffer-cannot-open-directory","errorCode":null,"errorMessage":"buffer.cannot_open_directory","messagePattern":"buffer\\.cannot_open_directory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/app/file_open_orchestrators.rs","lineNumber":1142,"sourceCode":"                        .canonicalize(parent)\n                        .unwrap_or_else(|_| parent.to_path_buf())\n                };\n                if let Some(filename) = resolved_path.file_name() {\n                    canonical_parent.join(filename)\n                } else {\n                    resolved_path\n                }\n            } else {\n                resolved_path\n            }\n        };\n        let path = canonical_path.as_path();\n\n        // Check if the path is a directory (after following symlinks via canonicalize)\n        // Directories cannot be opened as files in the editor\n        // Use filesystem trait method to support remote files\n        if self.authority().filesystem.is_dir(path).unwrap_or(false) {\n            anyhow::bail!(t!(\"buffer.cannot_open_directory\"));\n        }\n\n        // Check if file is already open - return existing buffer without switching\n        let already_open = self\n            .buffers\n            .iter()\n            .find(|(_, state)| state.buffer.file_path() == Some(path))\n            .map(|(id, _)| *id);\n\n        if let Some(id) = already_open {\n            return Ok(id);\n        }\n\n        // If the current buffer is empty and unmodified, replace it instead of creating a new one\n        // Note: Don't replace composite buffers (they appear empty but are special views).\n        // Suppressed when `allow_replace_empty` is false — see\n        // `open_file_for_preview` for the rationale.\n        let replace_current = allow_replace_empty && {","sourceCodeStart":1124,"sourceCodeEnd":1160,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/app/file_open_orchestrators.rs#L1124-L1160","documentation":"open_file_no_focus_inner uses filesystem.is_dir (after canonicalizing, so symlinks are resolved) and bails with a localized message when the target path is a directory, since directories cannot be opened as editable buffers.","triggerScenarios":"Calling open_file_no_focus / open_file_no_focus_with_kind / open_file_for_preview with a path that canonicalizes to a directory (is_dir returns true).","commonSituations":"Passing a directory path to a 'open file' command; opening a symlink that points at a directory; LSP or plugin handing the editor a folder URI.","solutions":["Check path.is_dir() before calling the open API and handle directories separately (e.g. open a file listing).","Pass a concrete file path inside the directory instead of the directory itself.","Resolve symlinks and verify the target is a regular file before opening."],"exampleFix":"// before\neditor.open_file(\"/home/user/project\")?; // a directory\n// after\nlet p = Path::new(\"/home/user/project\");\nif p.is_dir() { editor.open_directory_listing(p)?; } else { editor.open_file(p)?; }","handlingStrategy":"validation","validationCode":"let canon = std::fs::canonicalize(path)?; if canon.is_dir() { open_listing(&canon)?; return Ok(()); }","typeGuard":"fn is_openable_file(p: &Path) -> bool { std::fs::canonicalize(p).map(|c| c.is_file()).unwrap_or(false) }","tryCatchPattern":"if let Err(e) = editor.open_file(path) { if e.to_string().contains(\"cannot_open_directory\") { editor.open_directory_listing(path)?; } }","preventionTips":["Canonicalize paths and check is_dir before opening","Resolve symlinks — the check runs post-canonicalize","Never pass directory URIs from plugins/LSP to file-open APIs"],"tags":["filesystem","directory","invalid-argument"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}