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
- Make the field either a plain string ("services":"openai") or an array of strings (["openai","anthropic"])
- Ensure every array element is a string; convert numbers/booleans to strings if they are semantically names
- Use omission of the field (not null) to leave it unchanged
- 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
- Wrap proxy set payloads in a builder that types services as Vec<String> from the start
- Reject null for list fields in your own input layer; use omission for 'unchanged'
- Run args through the tool's JSON schema validator before execute
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
- Unsupported proxy service selector '{selector}'. Use tool `p
- Proxy is enabled but no proxy URL is configured. Set at leas
- proxy.scope='services' requires a non-empty proxy.services l
- matrix: `homeserver` is required
- Cannot persist empty Telegram identity
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/daa5b069bb718abb.
Report an issue: GitHub.