{"record":{"id":"c6d7012fa4d33687","repo":"zeroclaw-labs/zeroclaw","slug":"capability-requires-authored-with-configura","errorCode":null,"errorMessage":"capability '{}' requires authored `with` configuration to be an object","messagePattern":"capability '(.+?)' requires authored `with` configuration to be an object","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/sop/capability/registry.rs","lineNumber":123,"sourceCode":"        if result.success\n            && let Some(schema) = info.output_schema.as_ref()\n        {\n            schema::validate_value(schema, &result.output)\n                .with_context(|| format!(\"capability '{id}' output schema validation failed\"))?;\n        }\n        Ok(result)\n    }\n}\n\nfn authored_capability_input(capability: &dyn SopCapability, step: &SopStep) -> Result<Value> {\n    let configured = step.capability_input.clone().with_context(|| {\n        format!(\n            \"capability '{}' requires authored `with` configuration\",\n            capability.id()\n        )\n    })?;\n    if !configured.is_object() {\n        bail!(\n            \"capability '{}' requires authored `with` configuration to be an object\",\n            capability.id()\n        );\n    }\n    Ok(configured)\n}\n\nimpl std::fmt::Debug for SopCapabilityRegistry {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"SopCapabilityRegistry\")\n            .field(\"capabilities\", &self.ids())\n            .finish()\n    }\n}\n","sourceCodeStart":105,"sourceCodeEnd":138,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/sop/capability/registry.rs#L105-L138","documentation":"authored_capability_input() extracts the step's authored `with` value and requires it to be a JSON object (a mapping of capability options). A present-but-non-object value — string, number, array, boolean — bails. Used by validate_sop and execute_step, so it fails at both validation and execution time.","triggerScenarios":"Authoring a SOP step with a scalar or list `with`, e.g. `with: \"30\"`, `with: 5`, or `with: [1, 2]` instead of `with: { seconds: 30 }`. validate_sop surfaces it before any run starts.","commonSituations":"YAML authors writing a bare value for a single-option capability; JSON SOPs where with was inlined as a string; schema drift after a capability changed its options; copy-paste from docs showing shorthand that is not supported.","solutions":["Make `with` a mapping: `with: { <option>: <value> }` — even for a single option.","Run validate_sop on the SOP file to catch this before execution.","Check the capability's docs for its accepted option keys and shapes."],"exampleFix":"# before\n- uses: wait\n  with: 30\n\n# after\n- uses: wait\n  with:\n    seconds: 30","handlingStrategy":"type-guard","validationCode":"fn with_is_object(step: &SopStep) -> bool {\n    step.with.as_ref().map(serde_json::Value::is_object).unwrap_or(false)\n}\n// run validate_sop on every SOP file before deploying it","typeGuard":"fn is_capability_with_object(with: &serde_json::Value) -> bool {\n    with.is_object()\n}","tryCatchPattern":"match registry.authored_capability_input(&capability, &step.with) {\n    Err(e) if e.to_string().contains(\"to be an object\") => {\n        eprintln!(\"step 'uses {}': change `with` to a mapping, e.g. with: {{ key: value }}\", capability.id());\n    }\n    rest => rest?,\n}","preventionTips":["Always author `with` as a YAML/JSON mapping, even for a single option.","Wire validate_sop into SOP authoring CI so shape errors never reach execution.","JSON-schema-check step bodies against the capability's documented options."],"tags":["sop","capability","config","validation","schema","authoring"],"backgroundTag":"schema-validation-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}