zeroclaw-labs/zeroclaw · error

Missing 'app' or 'auth_config_id' for connect

Error message

Missing 'app' or 'auth_config_id' for connect

What it means

Hard input-validation bail in Tool::execute's 'connect' arm: neither args['app'] nor args['auth_config_id'] is present as a JSON string, so there is no target to connect. Unlike most composio failures, which come back as Ok(ToolResult{success:false, error:...}), this one propagates as an Err from execute() — callers that only inspect ToolResult fields will not see it.

Source

Thrown at crates/zeroclaw-tools/src/composio.rs:809

            }

            "connect" => {
                if let Err(error) = self
                    .security
                    .enforce_tool_operation(ToolOperation::Act, "composio.connect")
                {
                    return Ok(ToolResult {
                        success: false,
                        output: ToolOutput::default(),
                        error: Some(error),
                    });
                }

                let app = args.get("app").and_then(|v| v.as_str());
                let auth_config_id = args.get("auth_config_id").and_then(|v| v.as_str());

                if app.is_none() && auth_config_id.is_none() {
                    anyhow::bail!("Missing 'app' or 'auth_config_id' for connect");
                }

                match self
                    .get_connection_url(app, auth_config_id, entity_id)
                    .await
                {
                    Ok(link) => {
                        let target =
                            app.unwrap_or(auth_config_id.unwrap_or("provided auth config"));
                        let mut output =
                            format!("Open this URL to connect {target}:\n{}", link.redirect_url);
                        if let Some(connected_account_id) = link.connected_account_id.as_deref() {
                            if let Some(app_name) = app {
                                self.cache_connected_account(
                                    app_name,
                                    entity_id,
                                    connected_account_id,
                                );

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pass at least one of app (toolkit slug like 'slack') or auth_config_id as a string.
  2. Fix key names to exactly 'app' and 'auth_config_id'.
  3. Validate args against the tool's parameters_schema() before calling execute (see defense guard).

Example fix

// before
let args = json!({"action": "connect"});

// after
let args = json!({"action": "connect", "app": "slack", "entity_id": "alice"});
Defensive patterns

Strategy: validation

Validate before calling

// Check connect args before invoking the tool
fn require_connect_target(args: &serde_json::Value) -> anyhow::Result<()> {
    let target = ["app", "auth_config_id"].iter().find_map(|k| args.get(k));
    match target.and_then(|v| v.as_str()) {
        Some(s) if !s.trim().is_empty() => Ok(()),
        _ => anyhow::bail!("connect requires a non-empty 'app' or 'auth_config_id' string"),
    }
}

Type guard

fn has_connect_target(args: &serde_json::Value) -> bool {
    ["app", "auth_config_id"].iter().any(|k| {
        args.get(k)
            .and_then(|v| v.as_str())
            .map(|s| !s.trim().is_empty())
            .unwrap_or(false)
    })
}

Try / catch

// Note: this bail surfaces as Err from execute(), not as ToolResult{success:false}
let result = match tool.execute(args).await {
    Ok(r) => r,
    Err(e) if e.to_string().contains("Missing 'app' or 'auth_config_id'") => {
        ToolResult { success: false, output: Default::default(), error: Some("re-prompt for target app".into()) }
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: action='connect' with no other keys; app/auth_config_id present but not strings (null, numbers, nested objects — as_str() returns None); misspelled keys like 'appName' or 'authConfigId' that the arg extraction never reads.

Common situations: LLM omits the target app or uses wrong key casing; upstream code injects null placeholders for optional fields; JSON args built dynamically without checking the tool's parameters_schema().

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/4319c8931305ae79. Report an issue: GitHub.