{"record":{"id":"8ec6d6c1a350ff04","repo":"Hmbown/CodeWhale","slug":"command-string","errorCode":null,"errorMessage":"command string","messagePattern":"command string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/tools/subagent/tests.rs","lineNumber":8209,"sourceCode":"        runtime.context = ToolContext::new(workspace.clone());\n        runtime.worker_profile = WorkerRuntimeProfile::for_role(role.clone());\n        seed_read_only_role_deny_list(&mut runtime);\n        let registry = SubAgentToolRegistry::new(\n            runtime,\n            role.clone(),\n            None,\n            crate::tools::todo::new_shared_todo_list(),\n            crate::tools::plan::new_shared_plan_state(),\n        );\n\n        for input in [\n            json!({\"command\": \"pwd\"}),\n            json!({\"command\": git_log.as_str()}),\n            json!({\"command\": git_log.as_str(), \"timeout\": 5}),\n        ] {\n            let command = input[\"command\"]\n                .as_str()\n                .expect(\"command string\")\n                .to_string();\n            assert!(\n                registry.posture_permits_tool(\"bash\", Some(&input)),\n                \"{role:?} posture must admit {command}\"\n            );\n            assert!(\n                registry.envelope_refusal(\"bash\", &input).is_none(),\n                \"{role:?} envelope must admit {command}\"\n            );\n            let output = registry\n                .execute(\"agent_read_only_e2e\", \"bash\", input)\n                .await\n                .unwrap_or_else(|error| {\n                    panic!(\"{role:?} concrete executor must run {command}: {error}\")\n                });\n            assert!(!output.trim().is_empty(), \"{role:?} {command}\");\n        }\n    }","sourceCodeStart":8191,"sourceCodeEnd":8227,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/tests.rs#L8191-L8227","documentation":"In a posture-permission test (crates/tui/src/tools/subagent/tests.rs:8209), `input[\"command\"].as_str().expect(\"command string\")` asserts that the JSON test fixture has a `\"command\"` key holding a string. It is a test-local sanity check on fixture data. A panic means one of the iterated fixture objects lacks `\"command\"` or stores it as a non-string.","triggerScenarios":"Editing or adding a fixture in the loop `[json!({\"command\": \"pwd\"}), json!({\"command\": git_log.as_str()}), ...]` so a variant omits `\"command\"` or uses a non-string value.","commonSituations":"Renaming the fixture key, making `command` conditional, or building the JSON dynamically where the key is absent.","solutions":["Check every fixture in the iterated array has a string `\"command\"` field.","If a fixture legitimately has no command, handle it inside the loop before the `expect`.","Extract command extraction into a helper that returns `Option<&str>` and `assert!` with a descriptive message naming the failing fixture.","Add a compile-time or setup assertion that all fixtures share the same shape."],"exampleFix":"// before\nlet command = input[\"command\"].as_str().expect(\"command string\").to_string();\n// after\nlet command = input[\"command\"].as_str()\n    .unwrap_or_else(|| panic!(\"fixture missing string command: {input}\"))\n    .to_string();","handlingStrategy":"validation","validationCode":"// Validate fixture shape before the loop body\nfor input in fixtures {\n    assert!(input.get(\"command\").and_then(|c| c.as_str()).is_some(),\n            \"fixture missing string command: {input}\");\n}","typeGuard":"fn fixture_command(input: &serde_json::Value) -> Option<&str> {\n    input.get(\"command\").and_then(|v| v.as_str())\n}","tryCatchPattern":"// Fail loudly with the offending fixture\nlet command = input.get(\"command\").and_then(|v| v.as_str())\n    .unwrap_or_else(|| panic!(\"fixture missing string command: {input}\"));","preventionTips":["Keep all fixtures in a parameterized loop shape-identical.","Assert fixture schema once in a shared helper instead of scattering expects.","Include the fixture JSON in panic messages for quick diagnosis.","Review every new entry added to a fixture array for required keys."],"tags":["test","json","fixture","panic"],"backgroundTag":"missing-required-argument","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}