{"record":{"id":"5f73c275e5aa91dc","repo":"libnyanpasu/clash-nyanpasu","slug":"file-not-found","errorCode":null,"errorMessage":"file not found \"{}\"","messagePattern":"file not found \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/utils/help.rs","lineNumber":30,"sourceCode":"use serde_yaml::{Mapping, Value};\nuse std::{\n    io::{BufWriter, Cursor},\n    path::{Path, PathBuf},\n    str::FromStr,\n};\nuse tauri::{AppHandle, Manager, process::current_binary};\nuse tauri_plugin_shell::ShellExt;\nuse tracing::{debug, warn};\nuse tracing_attributes::instrument;\n\nuse crate::trace_err;\nuse tauri_plugin_opener::OpenerExt;\n\n/// read data from yaml as struct T\npub fn read_yaml<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T> {\n    let path = path.as_ref();\n    if !path.exists() {\n        bail!(\"file not found \\\"{}\\\"\", path.display());\n    }\n\n    let yaml_str = fs::read_to_string(path)\n        .with_context(|| format!(\"failed to read the file \\\"{}\\\"\", path.display()))?;\n\n    serde_yaml::from_str::<T>(&yaml_str).with_context(|| {\n        format!(\n            \"failed to read the file with yaml format \\\"{}\\\"\",\n            path.display()\n        )\n    })\n}\n\n/// read mapping from yaml fix #165\npub fn read_merge_mapping(path: &PathBuf) -> Result<Mapping> {\n    let mut val: Value = read_yaml(path)?;\n    val.apply_merge()\n        .with_context(|| format!(\"failed to apply merge \\\"{}\\\"\", path.display()))?;","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/utils/help.rs#L12-L48","documentation":"read_yaml was given a path that does not exist on disk. The function guards with path.exists() and bails before attempting to read, because callers expect a file to be present (e.g. a merge mapping or config YAML).","triggerScenarios":"Calling read_yaml::<T,_>(path) (directly or via read_merge_mapping) with a path to a file that was never created, was deleted, or whose path is wrong/typo'd.","commonSituations":"First launch before any user config has been written, switching data directories, or referencing an optional file (like a merge profile) without checking existence first.","solutions":["Verify the path printed in the message exists and is spelled correctly.","Call fs::create_dir_all on the parent and create a default file if it should always exist.","For optional files, check path.exists() before calling read_yaml and use a default value instead.","Confirm the app's data directory configuration points at the intended location."],"exampleFix":"// before\nlet mapping: MergeMapping = help::read_yaml(&path)?;\n// after\nlet mapping = if path.exists() {\n    help::read_yaml(&path)?\n} else {\n    MergeMapping::default()\n};","handlingStrategy":"validation","validationCode":"let path = Path::new(&config_path);\nif !path.exists() {\n    // create defaults before reading\n    if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; }\n    std::fs::write(path, default_yaml)?;\n}","typeGuard":"fn file_exists(p: &std::path::Path) -> bool { p.is_file() }","tryCatchPattern":"match read_yaml::<MergeMapping, _>(&path) {\n    Ok(v) => v,\n    Err(e) if e.to_string().starts_with(\"file not found\") => MergeMapping::default(),\n    Err(e) => return Err(e),\n}","preventionTips":["Check path.exists() before read_yaml for optional files","Create parent directories and seed default config on first launch","Validate data-dir configuration after upgrades or directory moves"],"tags":["yaml","filesystem","config"],"backgroundTag":"file-not-found","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}