{"record":{"id":"2ae6ea76f45fcf95","repo":"xai-org/grok-build","slug":"trust-store-path-has-no-parent","errorCode":null,"errorMessage":"trust store path has no parent","messagePattern":"trust store path has no parent","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/trust.rs","lineNumber":265,"sourceCode":"                \"folder trust: refusing to record an over-broad root (home, filesystem root, or non-absolute path); nothing recorded\"\n            );\n            return Ok(());\n        }\n\n        // No backing file (no-home env) → record nothing, return `Ok` so\n        // callers treat \"no home\" like \"nothing to persist\" (see fn doc).\n        let Some(path) = self.path.as_deref() else {\n            tracing::warn!(\n                path = %canonical.display(),\n                trusted,\n                \"folder trust: no user grok home resolved; trust decision not recorded\"\n            );\n            return Ok(());\n        };\n\n        // The lock file lives beside the store, so ensure the dir exists first.\n        let parent = path.parent().ok_or_else(|| {\n            io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"trust store path has no parent\",\n            )\n        })?;\n        std::fs::create_dir_all(parent)?;\n\n        // Serialize cross-process writers for the whole read-modify-write so a\n        // concurrent peer's records are preserved, not clobbered.\n        let _lock = ExclusiveLock::acquire(&path.with_extension(\"toml.lock\"))?;\n\n        // Re-read the latest on-disk state (merges a peer's concurrent writes).\n        let mut doc = Self::read_doc(path);\n        doc.folders.insert(\n            canonical.to_string_lossy().to_string(),\n            FolderTrust {\n                trusted,\n                decided_at: now_unix(),\n            },","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/trust.rs#L247-L283","documentation":"record_decision persists a trust decision to a store file and uses a lock file placed in the store path's parent directory. Before creating the directory it calls path.parent(); a Path has no parent only when it is a bare root (e.g. '/' with no file name or an empty/relative single-component path in effect). If there is no parent, it fails with io::ErrorKind::InvalidInput, 'trust store path has no parent'.","triggerScenarios":"Calling record_decision (directly or via set_trusted/set_untrusted) with a trust store path that has no parent component — e.g. an empty path, a bare root, or a path constructed as just a file name where parent() yields None (typically empty strings converted to a Path).","commonSituations":"Config value for the trust store left empty or unset and later coerced into a Path; misassembled path strings from environment variables; passing a root-only path instead of a full file path to the store.","solutions":["Configure a full file path for the trust store (e.g. ~/.config/xai-grok/trust.toml), not an empty or root-only path.","Validate the store path before calling: ensure path.parent() is Some and the file name is present.","Fix the environment/config source that supplies an empty trust-store path.","If the path is relative by design, make it absolute first so parent() is meaningful."],"exampleFix":"// before\nlet store: PathBuf = config.trust_store.unwrap_or_default().into(); // empty -> no parent\nset_trusted(&host, &store).await?;\n// after\nlet store = PathBuf::from(config.trust_store.unwrap_or_else(|| \"~/.config/xai-grok/trust.toml\".into()));\nassert!(store.parent().is_some(), \"trust store path needs a parent dir\");\nset_trusted(&host, &store).await?;","handlingStrategy":"validation","validationCode":"fn trust_store_ok(path: &std::path::Path) -> bool {\n    path.parent().map(|p| !p.as_os_str().is_empty()).unwrap_or(false)\n        && path.file_name().is_some()\n}\n// reject empty/root-only store paths at config load time","typeGuard":null,"tryCatchPattern":"match set_trusted(&host, &store).await {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"trust store path has no parent\") => {\n        let fixed = default_trust_store_path();\n        set_trusted(&host, &fixed).await?;\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always configure a full file path (with filename) for the trust store","Reject empty trust-store config values at startup","Make relative store paths absolute before use","Validate path.parent() is Some wherever you build the store path"],"tags":["configuration","path","trust-store","invalid-input"],"backgroundTag":"invalid-path","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}