tinyhumansai/openhuman · error · anyhow::Error
missing required string argument `{key}`
Error message
missing required string argument `{key}` What it means
Shared arg reader for the agent artifact tools: `read_required_str` (src/openhuman/agent/artifacts/tools.rs:40) errors when `args[key]` is absent, not a JSON string, or trims to empty. It guards `artifact_get`/`artifact_delete`'s `artifact_id` (and any other required string arg) before any store I/O happens.
Source
Thrown at src/openhuman/agent/artifacts/tools.rs:40
use crate::openhuman::tools::traits::{PermissionLevel, Tool, ToolResult};
/// Read `offset` / `limit` as optional `usize` from tool args.
fn read_opt_usize(args: &serde_json::Value, key: &str) -> Option<usize> {
args.get(key)
.and_then(serde_json::Value::as_u64)
.map(|v| v as usize)
}
/// Read a required, non-empty string arg.
fn read_required_str(args: &serde_json::Value, key: &str) -> anyhow::Result<String> {
let raw = args
.get(key)
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|s| !s.is_empty());
match raw {
Some(s) => Ok(s.to_string()),
None => Err(anyhow::anyhow!("missing required string argument `{key}`")),
}
}
/// List artifacts the agent has produced, newest first.
pub struct ArtifactListTool {
config: Arc<Config>,
}
impl ArtifactListTool {
pub fn new(config: Arc<Config>) -> Self {
Self { config }
}
}
#[async_trait]
impl Tool for ArtifactListTool {
fn name(&self) -> &str {
"artifact_list"View on GitHub (pinned to a221052e0d)
Solutions
- Include `"artifact_id": "<uuid>"` as a non-empty JSON string in the tool call arguments.
- Verify the exact key spelling against the tool's parameters_schema (`required: ["artifact_id"]`).
- If orchestrating programmatically, assert the field exists and is a non-empty trimmed string before dispatching the tool.
- Get a valid id first from artifact_list rather than guessing/hallucinating one.
Example fix
// before
{ "id": "550e8400-..." }
// after
{ "artifact_id": "550e8400-e29b-41d4-a716-446655440000" } Defensive patterns
Strategy: validation
Validate before calling
fn required_str_arg(args: &serde_json::Value, key: &str) -> Option<&str> {
args.get(key)?.as_str().map(str::trim).filter(|s| !s.is_empty())
}
let id = required_str_arg(&tool_args, "artifact_id")
.ok_or_else(|| format!("call must include non-empty string `{key}`", key = "artifact_id"))?; Type guard
fn has_required_string(args: &serde_json::Value, key: &str) -> bool {
args.get(key)
.and_then(serde_json::Value::as_str)
.map(|s| !s.trim().is_empty())
.unwrap_or(false)
} Prevention
- Validate tool args against the tool's parameters_schema before dispatch (required: ["artifact_id"]).
- Never pass numbers/nulls for id fields — serialize ids as JSON strings.
- Feed the model ids from artifact_list output instead of letting it guess.
When it happens
Trigger: An LLM tool call to artifact_get/artifact_delete whose arguments JSON omits `artifact_id`, passes a number/null/object instead of a string, or passes whitespace-only text; programmatic callers building args from unvalidated input.
Common situations: Model hallucinating the arg name (`id` instead of `artifact_id`); the id arriving as a JSON number or null from upstream serialization; copy-paste tool schemas drifting from the implemented required list.
Related errors
- artifact_list: {e}
- artifact_get: {e}
- artifact_delete: {e}
- Finish choosing how OpenHuman runs (tap Continue on the setu
- OpenHuman could not reach its remote (cloud) runtime. Check
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/1741511856be117a.
Report an issue: GitHub.