tinyhumansai/openhuman · error · anyhow::Error

composio.enable_trigger: connectionId must not be empty

Error message

composio.enable_trigger: connectionId must not be empty

What it means

ComposioClient::enable_trigger requires both a connectionId and a slug; this variant bails when the trimmed connectionId is empty, before POST /agent-integrations/composio/triggers is built. The connection must be one the caller owns — the id comes from list_connections or the available-triggers catalog.

Source

Thrown at src/openhuman/integrations/composio/client.rs:437

        };
        tracing::debug!(path = %path, "[composio] list_active_triggers");
        self.inner
            .get::<ComposioActiveTriggersResponse>(&path)
            .await
    }

    /// `POST /agent-integrations/composio/triggers` — enable a single
    /// trigger on a connection the caller owns.
    pub async fn enable_trigger(
        &self,
        connection_id: &str,
        slug: &str,
        trigger_config: Option<serde_json::Value>,
    ) -> Result<ComposioEnableTriggerResponse> {
        let connection_id = connection_id.trim();
        let slug = slug.trim();
        if connection_id.is_empty() {
            anyhow::bail!("composio.enable_trigger: connectionId must not be empty");
        }
        if slug.is_empty() {
            anyhow::bail!("composio.enable_trigger: slug must not be empty");
        }
        let mut body = json!({ "connectionId": connection_id, "slug": slug });
        if let Some(config) = trigger_config {
            body["triggerConfig"] = config;
        }
        tracing::debug!(slug = %slug, connection_id = %connection_id, "[composio] enable_trigger");
        self.inner
            .post::<ComposioEnableTriggerResponse>("/agent-integrations/composio/triggers", &body)
            .await
    }

    /// `DELETE /agent-integrations/composio/triggers/:triggerId`.
    pub async fn disable_trigger(
        &self,
        trigger_id: &str,

View on GitHub (pinned to 7491200858)

Solutions

  1. Make connection selection a hard prerequisite in the UI flow before enable is reachable
  2. Refresh connections and re-derive the id when the stored one is blank
  3. Validate both connectionId and slug together at the RPC boundary for a single clear error

Example fix

// before
client.enable_trigger(&selected.connection_id, &slug, cfg).await?;

// after
let Some(conn) = selected.connection_id.as_deref().map(str::trim).filter(|s| !s.is_empty()) else {
    anyhow::bail!("select a connection before enabling the trigger");
};
client.enable_trigger(conn, &slug, cfg).await?;
Defensive patterns

Strategy: validation

Validate before calling

let connection_id = connection_id.trim();
if connection_id.is_empty() {
    anyhow::bail!("a connection is required to enable a trigger");
}
client.enable_trigger(connection_id, slug, trigger_config).await?;

Type guard

fn is_non_empty_id(s: &str) -> bool {
    !s.trim().is_empty()
}

Prevention

When it happens

Trigger: Calling enable_trigger("", slug, config) or with a whitespace-only connection id — usually the enable action fired before a connection was chosen, or from a row whose connection reference was cleared.

Common situations: Trigger-enable UI with no connection selected; connection deleted concurrently while the enable dialog was open; connection id mapping dropped in a row-to-handler transform.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/564bc921ddb7c21d. Report an issue: GitHub.