zeroclaw-labs/zeroclaw · error · anyhow::Error

capability '{}' requires authored `with` configuration to be

Error message

capability '{}' requires authored `with` configuration to be an object

What it means

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.

Source

Thrown at crates/zeroclaw-runtime/src/sop/capability/registry.rs:123

        if result.success
            && let Some(schema) = info.output_schema.as_ref()
        {
            schema::validate_value(schema, &result.output)
                .with_context(|| format!("capability '{id}' output schema validation failed"))?;
        }
        Ok(result)
    }
}

fn authored_capability_input(capability: &dyn SopCapability, step: &SopStep) -> Result<Value> {
    let configured = step.capability_input.clone().with_context(|| {
        format!(
            "capability '{}' requires authored `with` configuration",
            capability.id()
        )
    })?;
    if !configured.is_object() {
        bail!(
            "capability '{}' requires authored `with` configuration to be an object",
            capability.id()
        );
    }
    Ok(configured)
}

impl std::fmt::Debug for SopCapabilityRegistry {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("SopCapabilityRegistry")
            .field("capabilities", &self.ids())
            .finish()
    }
}

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Make `with` a mapping: `with: { <option>: <value> }` — even for a single option.
  2. Run validate_sop on the SOP file to catch this before execution.
  3. Check the capability's docs for its accepted option keys and shapes.

Example fix

# before
- uses: wait
  with: 30

# after
- uses: wait
  with:
    seconds: 30
Defensive patterns

Strategy: type-guard

Validate before calling

fn with_is_object(step: &SopStep) -> bool {
    step.with.as_ref().map(serde_json::Value::is_object).unwrap_or(false)
}
// run validate_sop on every SOP file before deploying it

Type guard

fn is_capability_with_object(with: &serde_json::Value) -> bool {
    with.is_object()
}

Try / catch

match registry.authored_capability_input(&capability, &step.with) {
    Err(e) if e.to_string().contains("to be an object") => {
        eprintln!("step 'uses {}': change `with` to a mapping, e.g. with: {{ key: value }}", capability.id());
    }
    rest => rest?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/c6d7012fa4d33687. Report an issue: GitHub.