{"record":{"id":"82f6786dda8f4c90","repo":"Kuberwastaken/claurst","slug":"hooks-event-name-hook-is-missing-command","errorCode":null,"errorMessage":"hooks.{event_name} hook is missing command","messagePattern":"hooks\\.(.+?) hook is missing command","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/core/src/import_config.rs","lineNumber":737,"sourceCode":"                .as_object()\n                .ok_or_else(|| anyhow!(\"hooks.{event_name}[] must be an object\"))?;\n            let matcher = entry_obj\n                .get(\"matcher\")\n                .and_then(Value::as_str)\n                .unwrap_or(\"*\")\n                .to_string();\n            let hooks = entry_obj\n                .get(\"hooks\")\n                .and_then(Value::as_array)\n                .ok_or_else(|| anyhow!(\"hooks.{event_name}[].hooks must be an array\"))?;\n            for hook in hooks {\n                let hook_obj = hook\n                    .as_object()\n                    .ok_or_else(|| anyhow!(\"hooks.{event_name}[].hooks[] must be an object\"))?;\n                let command = hook_obj\n                    .get(\"command\")\n                    .and_then(Value::as_str)\n                    .ok_or_else(|| anyhow!(\"hooks.{event_name} hook is missing command\"))?\n                    .to_string();\n                hook_entries.push(HookEntry {\n                    command,\n                    tool_filter: if matcher == \"*\" { None } else { Some(matcher.clone()) },\n                    blocking: false,\n                });\n            }\n        }\n        out.insert(event, hook_entries);\n    }\n    Ok(out)\n}\n\nfn parse_hook_event(name: &str) -> Result<HookEvent> {\n    match name {\n        \"PreToolUse\" => Ok(HookEvent::PreToolUse),\n        \"PostToolUse\" => Ok(HookEvent::PostToolUse),\n        \"Stop\" => Ok(HookEvent::Stop),","sourceCodeStart":719,"sourceCodeEnd":755,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/core/src/import_config.rs#L719-L755","documentation":"In an imported hooks config, a command hook object under hooks.<event>[].hooks[] lacks the `command` field. The importer requires every hook entry to carry an explicit command string; hooks defined only with type or other keys are rejected.","triggerScenarios":"Importing a hook object like {\"type\": \"command\"} without the command value, {\"command\": 42}, or a hook with only \"url\"/\"prompt\" style fields from a different tool's schema.","commonSituations":"Migrating hooks from a tool whose hook objects use different key names, truncation during copy-paste, or quoting errors that made the command value a nested structure.","solutions":["Add \"command\": \"<shell command>\" (string) to every hook object under hooks.[].hooks[]","Rename tool-specific keys (cmd, run, script) to \"command\"","Ensure the command value is a plain quoted string, not a number, array, or object"],"exampleFix":"// before\n{ \"hooks\": [ { \"type\": \"command\" } ] }\n// after\n{ \"hooks\": [ { \"command\": \"./scripts/notify.sh\" } ] }","handlingStrategy":"validation","validationCode":"for (const groups of Object.values(cfg.hooks ?? {})) {\n  for (const g of groups) for (const h of g.hooks ?? []) if (typeof h?.command !== 'string') throw new Error('every hook needs a string \"command\"');\n}","typeGuard":"const hasCommand = (h) => typeof h === 'object' && h !== null && typeof h.command === 'string' && h.command.length > 0;","tryCatchPattern":"try { importConfig(path) } catch (e) { if (String(e).includes('hook is missing command')) { console.error('Add a string \"command\" field to the named event hook'); process.exitCode = 1; } else { throw e; } }","preventionTips":["Each hook object must contain a non-empty string \"command\"","Rename cmd/run/script keys to \"command\" when migrating configs","Ensure the command is quoted as a JSON string, not a number or array"],"tags":["config-import","validation","hooks","missing-field"],"backgroundTag":"missing-required-config-field","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}