{"record":{"id":"45d8b4761a6c8afc","repo":"zeroclaw-labs/zeroclaw","slug":"sop-name-not-found","errorCode":null,"errorMessage":"SOP '{name}' not found","messagePattern":"SOP '(.+?)' not found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/sop/mod.rs","lineNumber":266,"sourceCode":"    load_sops_from_directory(&dir, default_execution_mode)\n}\n\n/// Load a single SOP by directory name from the SOPs root. Errors if the\n/// directory or its `SOP.toml` is missing or malformed.\npub fn load_sop_by_name(\n    sops_dir: &Path,\n    name: &str,\n    default_execution_mode: SopExecutionMode,\n) -> Result<Sop> {\n    load_sop(&resolve_sop_dir(sops_dir, name)?, default_execution_mode)\n}\n\n/// Delete an SOP's directory (manifest, steps, everything). Errors if no\n/// SOP with that name exists.\npub fn delete_sop(sops_dir: &Path, name: &str) -> Result<()> {\n    let dir = resolve_sop_dir(sops_dir, name)?;\n    if !dir.exists() {\n        anyhow::bail!(\"SOP '{name}' not found\");\n    }\n    std::fs::remove_dir_all(&dir)?;\n    Ok(())\n}\n\n/// Create a new SOP on disk, refusing to overwrite an existing one. Same\n/// normalization and validation as `save_sop`.\npub fn create_sop(sops_dir: &Path, sop: &Sop) -> Result<()> {\n    if resolve_sop_dir(sops_dir, &sop.name)?.exists() {\n        anyhow::bail!(\"SOP '{}' already exists\", sop.name);\n    }\n    save_sop(sops_dir, sop)\n}\n\n/// Typed classification of an authoring failure so transports map it to the\n/// right status/RPC code without matching on stringified message substrings.\n#[derive(Debug)]\npub enum SopAuthorError {","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/sop/mod.rs#L248-L284","documentation":"delete_sop resolves the SOP's directory (with the same single-component validation as everything else) and refuses to delete when that directory does not exist. The SOP name may be misspelled, already deleted, or never created in this sops_dir.","triggerScenarios":"Calling delete_sop(sops_dir, name) after the SOP was already removed, with a typo in the name, or against the wrong sops_dir root (different install/config than where the SOP lives).","commonSituations":"Idempotent cleanup scripts that delete on every run; name casing or slug mismatches between create and delete; test teardown running against a fresh temp dir.","solutions":["Check the SOP exists (list SOPs or check resolve_sop_dir(...).exists()) before deleting.","Verify the exact name and the sops_dir root against the listing of loaded SOPs.","For cleanup scripts, treat 'not found' as the desired end state and swallow that specific error."],"exampleFix":"// before: blind delete in cleanup\ndelete_sop(&sops_dir, &name)?;\n\n// after: idempotent delete\nmatch delete_sop(&sops_dir, &name) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"not found\") => {\n        tracing::debug!(%name, \"SOP already gone\");\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"validation","validationCode":"if !resolve_sop_dir(&sops_dir, &name)?.exists() {\n    tracing::debug!(%name, \"SOP already absent\");\n    return Ok(());\n}\ndelete_sop(&sops_dir, &name)?;","typeGuard":null,"tryCatchPattern":"match delete_sop(&sops_dir, &name) {\n    Err(e) if e.to_string().contains(\"not found\") => Ok(()), // idempotent delete\n    other => other,\n}","preventionTips":["Make teardown scripts idempotent: absence is the goal state.","Confirm names against the loaded SOP list before deleting.","Verify the sops_dir root matches the install that owns the SOP."],"tags":["sop","delete","not-found"],"backgroundTag":"entity-not-found","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}