{"record":{"id":"6e7be0e4c94678e9","repo":"flxzt/rnote","slug":"failed-to-get-file-name-from-output-file","errorCode":null,"errorMessage":"Failed to get file name from output-file \"{}\".","messagePattern":"Failed to get file name from output-file \"(.+?)\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-cli/src/export.rs","lineNumber":571,"sourceCode":"            ..\n        } => {\n            select_strokes_for_selection_args(engine, selection, *selection_collision);\n            let export_bytes = engine\n                .export_selection(None)\n                .await??\n                .context(\"Exporting selection failed, no strokes selected.\")?;\n            cli::create_overwrite_file_w_bytes(&output_file, &export_bytes).await?;\n            if open {\n                cli::open_file_default_app(output_file)?;\n            }\n        }\n        cli::ExportCommand::Doc { .. } => {\n            let Some(export_file_name) = output_file\n                .as_ref()\n                .file_name()\n                .map(|s| s.to_string_lossy().to_string())\n            else {\n                return Err(anyhow::anyhow!(\n                    \"Failed to get file name from output-file \\\"{}\\\".\",\n                    output_file.as_ref().display()\n                ));\n            };\n            let export_bytes = engine.export_doc(export_file_name, None).await??;\n            cli::create_overwrite_file_w_bytes(&output_file, &export_bytes).await?;\n            if open {\n                cli::open_file_default_app(output_file)?;\n            }\n        }\n        cli::ExportCommand::DocPages {\n            output_dir,\n            output_file_stem,\n            export_format: output_format,\n            ..\n        } => {\n            validators::path_is_dir(output_dir)?;\n            // The output file cannot be set with this subcommand","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-cli/src/export.rs#L553-L589","documentation":"export_to_file failed to derive an export file name from the --output-file path. Path::file_name() returns None only when the path terminates in '..' or is the root, so the CLI refuses to guess a name for the exported document.","triggerScenarios":"Running `rnote-cli export doc` with an output-file path ending in '..' (e.g. 'out/..') or pointing at the filesystem root, so Path::file_name() yields None.","commonSituations":"Shell-expanded paths like '--output-file $dir/..' meant to target a directory; scripts constructing paths by naive string concatenation that end with a trailing '..' or '/'.","solutions":["Pass a concrete file path with a final component (e.g. 'out/doc.rnote'), not a path ending in '..' or '/'","Normalize the path in a wrapper script before invoking the CLI (realpath)","Check the output path with Path::file_name().is_some() before calling the export command"],"exampleFix":"// before\nrnote-cli export doc --output-file out/..\n// after\nrnote-cli export doc --output-file out/doc.rnote","handlingStrategy":"validation","validationCode":"fn has_file_name(p: &Path) -> bool { p.file_name().is_some() }\nif !has_file_name(output_file) { eprintln!(\"--output-file must end in a real file name\"); std::process::exit(2); }","typeGuard":"fn is_valid_output_path(p: &Path) -> bool {\n    p.file_name().is_some() && !p.is_dir()\n}","tryCatchPattern":"match export_result {\n    Err(e) if e.to_string().contains(\"Failed to get file name\") => {\n        eprintln!(\"Invalid --output-file path; provide a path ending in a file name\");\n    }\n    Err(e) => return Err(e),\n    Ok(bytes) => { /* write bytes */ }\n}","preventionTips":["Always pass output paths ending in a concrete file name","Avoid trailing '..' or '/' in path arguments","Normalize paths with canonicalize/realpath in scripts"],"tags":["cli","path","filesystem"],"backgroundTag":"invalid-argument-format","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}