{"record":{"id":"1ec90d607ec549c3","repo":"flxzt/rnote","slug":"expected-file-with-extension-expected-ext-fou","errorCode":null,"errorMessage":"Expected file with extension \"{expected_ext}\", found extension \"{ext:?}\", file \"{}\".","messagePattern":"Expected file with extension \"(.+?)\", found extension \"(.+?)\", file \"(.+?)\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-cli/src/validators.rs","lineNumber":27,"sourceCode":"    }\n    Ok(())\n}\n\npub(crate) fn path_is_file(path: &Path) -> anyhow::Result<()> {\n    if !path.is_file() {\n        return Err(anyhow::anyhow!(\n            \"Expected file, found directory \\\"{}\\\"\",\n            path.display()\n        ));\n    }\n    Ok(())\n}\n\npub(crate) fn file_has_ext(path: &Path, expected_ext: &str) -> anyhow::Result<()> {\n    path_is_file(path)?;\n    match path.extension() {\n        Some(ext) if ext == expected_ext => Ok(()),\n        Some(ext) => Err(anyhow::anyhow!(\n            \"Expected file with extension \\\"{expected_ext}\\\", found extension \\\"{ext:?}\\\", file \\\"{}\\\".\",\n            path.display()\n        )),\n        None => Err(anyhow::anyhow!(\n            \"Expected file with extension \\\"{expected_ext}\\\", no extension found for file \\\"{}\\\".\",\n            path.display()\n        )),\n    }\n}\n","sourceCodeStart":9,"sourceCodeEnd":37,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-cli/src/validators.rs#L9-L37","documentation":"file_has_ext found the file but its extension does not match the expected one (e.g. an input was expected to be '.xopp' but had a different extension). The actual extension is included in the message via Debug formatting.","triggerScenarios":"Supplying a file with the wrong extension to an argument validated with file_has_ext(path, \"xopp\") — e.g. renaming a PDF to .xopp, or passing an .rnote file where .xopp is required.","commonSituations":"Files downloaded without extensions; manual renames; mixing up the rnote and xopp inputs on import/export commands.","solutions":["Rename or re-export the file with the correct extension (e.g. mv drawing.txt drawing.xopp only if it truly is a XOPP file)","Double-check which command expects which format and pass the matching file","Verify the extension in scripts with Path::extension() before invoking"],"exampleFix":"// before\nrnote-cli import sketch.rnote out.rnote   # expects .xopp\n// after\nrnote-cli import sketch.xopp out.rnote","handlingStrategy":"validation","validationCode":"fn has_ext(p: &Path, ext: &str) -> bool {\n    p.extension().map_or(false, |e| e == ext)\n}\nassert!(has_ext(Path::new(\"sketch.xopp\"), \"xopp\"));","typeGuard":"fn is_xopp(p: &Path) -> bool {\n    p.extension().map_or(false, |e| e == \"xopp\")\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"found extension\") => {\n        eprintln!(\"Wrong file type; the command expects a different extension\");\n    }\n    other => other,\n}","preventionTips":["Check the extension matches the command's expected format before running","Don't blind-rename files to fix extension errors; confirm actual format","Keep rnote and xopp inputs clearly separated in scripts"],"tags":["validation","file-extension","cli"],"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"}