tinyhumansai/openhuman · error · anyhow::Error
composio.execute_tool: tool slug must not be empty
Error message
composio.execute_tool: tool slug must not be empty
What it means
execute_with_auth_retry rejects a tool slug that is empty after trimming, before building the request body. This is a client-side precondition guard on the auth-retry entry point, deliberately mirroring the guards in execute_tool and execute_tool_once so a blank slug never reaches Composio. It logs a debug record with the raw slug length before bailing.
Source
Thrown at src/openhuman/integrations/composio/auth_retry.rs:78
}
/// Test-visible inner form that takes an explicit backoff so unit tests
/// can drive the retry path without sleeping for real seconds.
pub(crate) async fn execute_with_auth_retry_inner(
client: &ComposioClient,
slug: &str,
args: Option<serde_json::Value>,
backoff: Duration,
connection_id: Option<&str>,
) -> anyhow::Result<ComposioExecuteResponse> {
let tool = slug.trim();
if tool.is_empty() {
tracing::debug!(
target: "composio",
raw_slug_len = slug.len(),
"[composio][auth_retry] rejecting empty tool slug"
);
anyhow::bail!("composio.execute_tool: tool slug must not be empty");
}
let arguments = args.unwrap_or(serde_json::Value::Object(Default::default()));
let has_args = arguments.as_object().is_some_and(|a| !a.is_empty());
let mut body = serde_json::json!({ "tool": tool, "arguments": arguments });
if let Some(cid) = connection_id.map(str::trim).filter(|s| !s.is_empty()) {
body["connectionId"] = serde_json::json!(cid);
}
tracing::debug!(
target: "composio",
slug = %tool,
has_args,
connection_id = ?connection_id,
"[composio][auth_retry] execute start"
);
client
.execute_tool_with_post_oauth_retry(tool, &body, backoff)
.awaitView on GitHub (pinned to 7491200858)
Solutions
- Fix the caller that produced the slug — an empty slug is always a caller bug, never a Composio state problem
- Trim and validate the slug before invoking, and re-prompt the agent (or skip) when it is blank
- If slugs come from parsed tool definitions, assert non-empty at parse time so the bad data is caught at its source
Example fix
// before
let resp = execute_with_auth_retry(&slug, args, backoff, conn).await?;
// after
let slug = slug.trim();
if slug.is_empty() {
anyhow::bail!("agent produced an empty composio action slug; re-prompt");
}
let resp = execute_with_auth_retry(slug, args, backoff, conn).await?; Defensive patterns
Strategy: validation
Validate before calling
// Validate before entering the auth-retry path
let slug = slug.trim();
if slug.is_empty() {
tracing::warn!("[agent] composio tool call had an empty slug; skipping");
return Ok(None); // or re-prompt the model for a valid action
}
let resp = execute_with_auth_retry(slug, args, backoff, connection_id).await?; Type guard
fn is_non_empty_slug(s: &str) -> bool {
!s.trim().is_empty()
} Try / catch
match execute_with_auth_retry(slug, args, backoff, conn).await {
Ok(resp) => Ok(resp),
Err(err) if err.to_string().contains("tool slug must not be empty") => {
re_prompt_agent_for_action().await // caller bug: recover by asking again
}
Err(err) => Err(err),
} Prevention
- Validate action names where model tool calls are deserialized, not deep in the HTTP client
- Reject blank slugs in agent tool schemas (minLength on the action field) so producers fail early
- Add a shared trim+check helper at every composio entry point instead of relying on the server-side bounce
When it happens
Trigger: Calling composio::auth_retry::execute_with_auth_retry("", args, backoff, connection_id) or with a slug of only whitespace. Typically an agent/LLM tool call whose action/slug field is missing or blank.
Common situations: LLM emits a tool call with an empty name but populated arguments; template/format! interpolation that produced an empty slug; caller defaults the slug to an empty string instead of erroring earlier.
Related errors
- composio.authorize: toolkit must not be empty
- composio.delete_connection: connectionId must not be empty
- composio.execute_tool: tool slug must not be empty
- composio.execute_tool_once: tool slug must not be empty
- composio.create_trigger: slug must not be empty
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/4b585d81c6655ed6.
Report an issue: GitHub.