{"record":{"id":"c18b8fd47fc45ca6","repo":"screenpipe/screenpipe","slug":"cannot-determine-parent-dir-of","errorCode":null,"errorMessage":"cannot determine parent dir of {:?}","messagePattern":"cannot determine parent dir of (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/screenpipe-core/src/pipes/mod.rs","lineNumber":7272,"sourceCode":"        .find(\"\\n---\")\n        .ok_or_else(|| anyhow!(\"could not find closing --- in front-matter\"))?;\n\n    let yaml_str = &rest[..end];\n    let body = rest[end + 4..].trim().to_string();\n\n    let config: PipeConfig = serde_yaml::from_str(yaml_str)?;\n\n    Ok((config, body))\n}\n\n/// Atomic file write: write to a temp file in the same directory, then rename.\n/// On Unix, rename is atomic. On Windows, this avoids the partial-write window\n/// where a concurrent reader (e.g. the scheduler) sees a truncated file.\nfn atomic_write(path: &Path, content: &str) -> Result<()> {\n    use std::io::Write;\n    let dir = path\n        .parent()\n        .ok_or_else(|| anyhow!(\"cannot determine parent dir of {:?}\", path))?;\n    let mut tmp = tempfile::NamedTempFile::new_in(dir)?;\n    tmp.write_all(content.as_bytes())?;\n    tmp.flush()?;\n    // persist atomically (rename on Unix, MoveFileEx on Windows)\n    tmp.persist(path)?;\n    Ok(())\n}\n\n/// Serialize a PipeConfig + body back to pipe.md format.\n/// Name is excluded from frontmatter (derived from directory name).\npub fn serialize_pipe(config: &PipeConfig, body: &str) -> Result<String> {\n    let mut cfg = config.clone();\n    cfg.name = String::new(); // empty → skip_serializing_if kicks in\n\n    // Remove legacy \"config\" key from extras — old pipe.md files had a nested\n    // `config: { enabled: true }` block that gets captured by the flattened\n    // HashMap and re-emitted forever. Also strip any keys that shadow real\n    // struct fields to prevent duplicates.","sourceCodeStart":7254,"sourceCodeEnd":7290,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-core/src/pipes/mod.rs#L7254-L7290","documentation":"atomic_write writes pipe files via a temp file plus atomic rename/persist. It needs the target's parent directory to place the temp file; if path.parent() is None (path has no directory component, e.g. a bare relative filename), it throws this error.","triggerScenarios":"Calling a pipe-writing operation that ends in atomic_write with a Path like \"pipe.md\" (no directory prefix) or a root-less path constructed from components only.","commonSituations":"Programmatically building paths as Path::new(\"file.md\") instead of joining a directory; passing a filename from config without resolving it against the pipe directory.","solutions":["Join the filename onto an absolute directory before writing: PathBuf::from(pipe_dir).join(\"pipe.md\").","Call canonicalize() (or std::env::current_dir().join(...)) on relative paths before passing them.","Pass paths derived from the pipe's install directory rather than bare names."],"exampleFix":"// before\natomic_write(Path::new(\"pipe.md\"), content)?;\n// after\nlet path = pipe_dir.join(\"pipe.md\");\natomic_write(&path, content)?;","handlingStrategy":"validation","validationCode":"const path = require('path');\nconst p = path.resolve(targetPath); // ensures a directory component exists\nif (path.dirname(p) === p) throw new Error('path has no parent directory: ' + p);","typeGuard":"fn has_parent(path: &Path) -> bool {\n    path.parent().is_some()\n}","tryCatchPattern":"match atomic_write(&path, content) {\n    Err(e) if e.to_string().starts_with(\"cannot determine parent dir\") => {\n        eprintln!(\"pass a path with a directory component, e.g. dir.join(\\\"pipe.md\\\")\");\n    }\n    other => other?,\n}","preventionTips":["Always build write targets as directory.join(filename), never bare filenames.","Canonicalize user-supplied paths before persistence.","Assert Path::parent().is_some() in debug builds for write helpers."],"tags":["filesystem","pipes","atomic-write","path"],"backgroundTag":"invalid-path","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}