tinyhumansai/openhuman · warning
invalid approvalMode type (expected required|not_required|nu
Error message
invalid approvalMode type (expected required|not_required|null)
What it means
CardPatch parsing: args["approvalMode"] is present, is not null, and is not a string (todo.rs:263) — e.g. true, 1, an array, or an object. The accepted shapes are exactly the strings "required"/"not_required" or JSON null; anything else fails with this type error before value validation even starts.
Source
Thrown at src/openhuman/agent/tools/todo.rs:263
}
fn patch_from_args(args: &serde_json::Value) -> anyhow::Result<CardPatch> {
let status: Option<TaskCardStatus> = match args.get("status").and_then(|v| v.as_str()) {
Some(s) => Some(ops::parse_status(s).map_err(anyhow::Error::msg)?),
None => None,
};
let approval_mode = match args.get("approvalMode") {
Some(value) if value.is_null() => Some(None),
Some(value) => match value.as_str() {
Some("required") => Some(Some(TaskApprovalMode::Required)),
Some("not_required") => Some(Some(TaskApprovalMode::NotRequired)),
Some(other) => {
return Err(anyhow::anyhow!(
"invalid approvalMode '{other}' (expected required|not_required|null)"
))
}
None => {
return Err(anyhow::anyhow!(
"invalid approvalMode type (expected required|not_required|null)"
))
}
},
None => None,
};
Ok(CardPatch {
content: None,
status,
objective: optional_string(args, "objective"),
plan: optional_string_array(args, "plan")?,
assigned_agent: optional_string(args, "assignedAgent"),
allowed_tools: optional_string_array(args, "allowedTools")?,
approval_mode,
acceptance_criteria: optional_string_array(args, "acceptanceCriteria")?,
evidence: optional_string_array(args, "evidence")?,
notes: optional_string(args, "notes"),
blocker: optional_string(args, "blocker"),View on GitHub (pinned to a221052e0d)
Solutions
- Send approvalMode as a string ("required"/"not_required") or null — never a boolean or object
- In wrappers, map boolean tri-state (true/false/absent) to the string/null literals explicitly
- Omit the field entirely when no override is needed
Example fix
// before
{ "op": "edit", "id": "t1", "approvalMode": true }
// after
{ "op": "edit", "id": "t1", "approvalMode": "required" } Defensive patterns
Strategy: type-guard
Validate before calling
const a = args as Record<string, unknown>;
if (a?.approvalMode !== undefined && a.approvalMode !== null
&& typeof a.approvalMode !== "string") {
throw new Error("approvalMode must be a string or null, not " + typeof a.approvalMode);
} Type guard
function isApprovalModeValue(v: unknown): v is string | null {
return v === null || typeof v === "string";
} Try / catch
if e.to_string().contains("invalid approvalMode type") {
return Ok(ToolResult::error("approvalMode must be the string 'required'/'not_required' or null — booleans/objects are rejected"));
} Prevention
- Never serialize approvalMode as a boolean or object — it is string|null on the wire
- Map boolean tri-state flags to the string literals explicitly in client code
- Omit the field when no override change is intended
When it happens
Trigger: Passing a boolean (approvalMode: true), a number, or a nested config object; serializers that map tri-state enums to booleans instead of string|null.
Common situations: Client models with a boolean approval flag; models inventing structured payloads for a scalar field.
Related errors
- missing required field `op`
- missing `cards` for op=replace
- missing required field `{key}`
- invalid approvalMode '{other}' (expected required|not_requir
- Missing 'agent' parameter
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/966f1b2053a17aa9.
Report an issue: GitHub.