{"record":{"id":"1f55636694142662","repo":"xai-org/grok-build","slug":"not-a-directory-path","errorCode":null,"errorMessage":"Not a directory: {path}","messagePattern":"Not a directory: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/plugin_cmd.rs","lineNumber":683,"sourceCode":"            .as_deref()\n            .map(|s| format!(\" (subdir: {s})\"))\n            .unwrap_or_default();\n        println!(\"    {pname}{ver}{sub}\");\n    }\n\n    if let Ok(ManifestLoadResult::Found(manifest)) = load_manifest(&repo.path) {\n        if let Some(ref desc) = manifest.description {\n            println!(\"  description: {desc}\");\n        }\n        print_component_summary(&manifest, &repo.path);\n    }\n    Ok(())\n}\n\nfn cmd_validate(path: &str) -> Result<()> {\n    let root = PathBuf::from(path);\n    if !root.is_dir() {\n        bail!(\"Not a directory: {path}\");\n    }\n    match load_manifest(&root) {\n        Ok(ManifestLoadResult::Found(manifest)) => {\n            manifest\n                .validate()\n                .map_err(|e| anyhow::anyhow!(\"Manifest validation failed: {e}\"))?;\n            println!(\"Plugin manifest is valid.\");\n            println!(\"  name: {}\", manifest.name);\n            if let Some(ref v) = manifest.version {\n                println!(\"  version: {v}\");\n            }\n            if let Some(ref d) = manifest.description {\n                println!(\"  description: {d}\");\n            }\n            print_component_summary(&manifest, &root);\n            Ok(())\n        }\n        Ok(ManifestLoadResult::NotFound) => {","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/plugin_cmd.rs#L665-L701","documentation":"`cmd_validate` takes a filesystem path, converts it to a PathBuf, and immediately bails with `Not a directory: {path}` if the path exists but is not a directory (or, per `is_dir()`, is not an accessible directory). The validation pipeline (`load_manifest` and `manifest.validate()`) only runs on directory roots containing a plugin manifest.","triggerScenarios":"`grok plugin validate <path>` where <path> points at a file (e.g. the manifest file itself instead of its containing directory), an empty/typo'd path, or a path whose parent components are not accessible so is_dir() returns false.","commonSituations":"Passing plugin.toml/manifest file path instead of the plugin root; wrong working directory in scripts; deleted or renamed plugin directory; symlinks to files rather than directories.","solutions":["Pass the plugin root directory, not the manifest file: grok plugin validate ./my-plugin","Verify the path exists and is a directory: test -d <path>","Fix typos/absolute vs relative path mistakes (use pwd / ls to confirm)","Check symlink targets resolve to directories"],"exampleFix":"# before\n$ grok plugin validate ./my-plugin/plugin.toml\nError: Not a directory: ./my-plugin/plugin.toml\n\n# after\n$ grok plugin validate ./my-plugin","handlingStrategy":"validation","validationCode":"fn assert_plugin_root(path: &str) -> Result<(), String> {\n    let p = std::path::Path::new(path);\n    if !p.is_dir() {\n        return Err(format!(\"'{path}' is not a directory; pass the plugin root containing the manifest\"));\n    }\n    Ok(())\n}","typeGuard":"fn is_dir_path(p: &str) -> bool {\n    std::path::Path::new(p).is_dir()\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().starts_with(\"Not a directory\") => {\n        eprintln!(\"Pass the plugin root directory, not the manifest file.\");\n    }\n    other => other?,\n}","preventionTips":["Validate the target with test -d before scripting validate","Never pass the manifest file itself; always its parent directory","Use absolute paths in CI to avoid cwd surprises","Resolve symlinks and confirm they point at directories"],"tags":["cli","plugin-validate","path-validation","filesystem"],"backgroundTag":"invalid-path-argument","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}