{"record":{"id":"3fea549832ac9bea","repo":"flxzt/rnote","slug":"could-not-retrieve-basename-for-file-file","errorCode":null,"errorMessage":"Could not retrieve basename for file: `{file:?}`.","messagePattern":"Could not retrieve basename for file: `(.+?)`\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/rnote-ui/src/canvas/imexport.rs","lineNumber":233,"sourceCode":"    /// - `Ok(false)` if a save was already in progress (and thus this function didn't do anything)\n    /// - `Err(e)` when saving failed in any way\n    #[tracing::instrument(skip_all, fields(path = format!(\"{:?}\", file.path())))]\n    pub(crate) async fn save_document_to_file(&self, file: &gio::File) -> anyhow::Result<bool> {\n        // skip saving when it is already in progress\n        if self.save_in_progress() {\n            debug!(\"Returning early, saving file is already in progress\");\n            return Ok(false);\n        }\n        self.set_save_in_progress(true);\n        debug!(\"Saving file is now in progress\");\n\n        let filepath = file.path().ok_or_else(|| {\n            self.set_save_in_progress(false);\n            anyhow::anyhow!(\"Could not get a path for file: `{file:?}`.\")\n        })?;\n        let basename = file.basename().ok_or_else(|| {\n            self.set_save_in_progress(false);\n            anyhow::anyhow!(\"Could not retrieve basename for file: `{file:?}`.\")\n        })?;\n        let rnote_bytes_receiver = self\n            .engine_ref()\n            .save_as_rnote_bytes(basename.to_string_lossy().to_string());\n\n        let mut skip_set_output_file = false;\n        if let Some(output_filepath) = self.output_file().and_then(|f| f.path())\n            && crate::utils::paths_abs_eq(output_filepath, &filepath).unwrap_or(false)\n        {\n            skip_set_output_file = true;\n        }\n\n        self.dismiss_output_file_modified_toast();\n\n        let file_write_operation = async {\n            let bytes = rnote_bytes_receiver.await??;\n            // The `output_file_expect_write` should theoretically be reset to `false` by the file watcher later.\n            self.set_output_file_expect_write(true);","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-ui/src/canvas/imexport.rs#L215-L251","documentation":"Thrown in `save_document_to_file` when `gio::File::basename()` returns None, i.e. the GFile has no extractable base name. This happens when the file URI cannot be parsed into a concrete filesystem path (e.g. a non-file URI scheme or a failure querying the file info). Before failing, the save-in-progress flag is reset so the UI does not hang in a saving state.","triggerScenarios":"Calling `save_document_to_file` with a GFile whose `path()` resolved but whose `basename()` query fails or returns None — typically a file backed by a non-filesystem URI (e.g. http://, trash://, recent://) or a backend that does not support the `standard::name` attribute.","commonSituations":"Saving via a portal/remote location or mount that exposes URIs without local paths; a stale or cancelled file chooser handle; gvfs-backed URIs where attribute query is unavailable.","solutions":["Ensure the save dialog returns a local filesystem URI/path (Gio.File::new_for_path or a real chosen file), not a scheme-less or remote URI.","Handle the None basename case explicitly with a user-visible message instead of an anyhow bail.","If remote/portal locations must be supported, fall back to deriving a name from `file.uri()` or the document title.","Verify the storage backend (gvfs mount, network share) supports basic attribute queries."],"exampleFix":"// before\nlet basename = file.basename().ok_or_else(|| {\n    self.set_save_in_progress(false);\n    anyhow::anyhow!(\"Could not retrieve basename for file: `{file:?}`.\")\n})?;\n// after\nlet basename = file.basename().or_else(|| {\n    file.uri()\n        .split('/')\n        .last()\n        .and_then(|s| if s.is_empty() { None } else { Some(glib::filename_display_basename(&file.path()?)) })\n}).ok_or_else(|| {\n    self.set_save_in_progress(false);\n    anyhow::anyhow!(\"Could not retrieve basename for file: `{file:?}`.\")\n})?;","handlingStrategy":"validation","validationCode":"let is_regular = file.query_file_type(gio::FileQueryInfoFlags::NONE, gio::Cancellable::NONE) == gio::FileType::Regular;\nlet path_ok = file.path().is_some();\nif !(is_regular && path_ok) { bail!(\"file has no usable local path/basename\"); }","typeGuard":"fn has_basename(file: &gio::File) -> bool {\n    file.path().map(|p| p.file_name().is_some()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Always obtain the save target from a FileChooser returning local paths","Reject remote/unsupported URI schemes before starting the save flow","Keep the UI save-in-progress flag in sync in both success and error paths"],"tags":["gio","file-io","uri","save-document"],"backgroundTag":"file-not-found","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}