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

'{field}' must be a string or string[]

Error message

'{field}' must be a string or string[]

What it means

Proxy config's set action parses list-typed fields (such as services) with parse_string_list, which accepts exactly a JSON string or an array of JSON strings. Any other shape for the named field — number, boolean, object, null, or an array containing non-string entries — bails with this message naming the field.

Source

Thrown at crates/zeroclaw-tools/src/proxy_config.rs:121

                let value = item.as_str().ok_or_else(|| {
                    ::zeroclaw_log::record!(
                        WARN,
                        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
                            .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                            .with_attrs(::serde_json::json!({"field": field})),
                        "proxy_config: array element must be a string"
                    );
                    anyhow::Error::msg(format!("'{field}' array must only contain strings"))
                })?;
                let trimmed = value.trim();
                if !trimmed.is_empty() {
                    out.push(trimmed.to_string());
                }
            }
            return Ok(out);
        }

        anyhow::bail!("'{field}' must be a string or string[]")
    }

    fn parse_optional_string_update(args: &Value, field: &str) -> anyhow::Result<MaybeSet<String>> {
        let Some(raw) = args.get(field) else {
            return Ok(MaybeSet::Unset);
        };

        if raw.is_null() {
            return Ok(MaybeSet::Null);
        }

        let value = raw
            .as_str()
            .ok_or_else(|| {
                ::zeroclaw_log::record!(
                    WARN,
                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Make the field either a plain string ("services":"openai") or an array of strings (["openai","anthropic"])
  2. Ensure every array element is a string; convert numbers/booleans to strings if they are semantically names
  3. Use omission of the field (not null) to leave it unchanged
  4. Validate the args against the tool's JSON schema before submitting

Example fix

// before
{"action":"set","proxy":{"enabled":true,"url":"http://127.0.0.1:7890"},"services":["openai",42]}
// after
{"action":"set","proxy":{"enabled":true,"url":"http://127.0.0.1:7890"},"services":["openai","42"]}
Defensive patterns

Strategy: validation

Validate before calling

// Validate a string-or-string[] field before calling set
fn is_string_or_string_list(v: &serde_json::Value) -> bool {
    match v {
        serde_json::Value::String(_) => true,
        serde_json::Value::Array(items) => items.iter().all(|i| i.is_string()),
        _ => false,
    }
}

Type guard

fn is_string_or_string_list(v: &serde_json::Value) -> bool {
    match v {
        serde_json::Value::String(_) => true,
        serde_json::Value::Array(items) => items.iter().all(|i| i.is_string()),
        _ => false,
    }
}

Try / catch

Err(e) if e.to_string().contains("must be a string or string[]") => {
    // re-read the named field from user input, stringify entries, resubmit once
}

Prevention

When it happens

Trigger: Tool args like {"action":"set","services":["anthropic",3]}, {"services":{"0":"anthropic"}}, or {"services":null}; also arrays where one entry is an object or a number.

Common situations: Generated or hand-edited JSON args where a single value is naturally written as a scalar but the field is declared string[]; YAML-to-JSON conversions that turn a one-element list into a scalar; null used to mean 'unset'.

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/daa5b069bb718abb. Report an issue: GitHub.