tinyhumansai/openhuman · error · anyhow::Error

composio.enable_trigger: slug must not be empty

Error message

composio.enable_trigger: slug must not be empty

What it means

The second precondition of enable_trigger: the trigger slug must be non-empty after trimming before POST /agent-integrations/composio/triggers is built. It fires when the connection id is valid but the slug identifying the trigger type is blank.

Source

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

            .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,
    ) -> Result<ComposioDisableTriggerResponse> {
        let trigger_id = trigger_id.trim();
        if trigger_id.is_empty() {

View on GitHub (pinned to 7491200858)

Solutions

  1. Require a trigger row/template selection before the enable action is available
  2. Validate the slug against list_available_triggers output to catch both blank and unknown slugs
  3. If the slug comes from deserialized catalog data, fail at deserialization with row context

Example fix

// before
client.enable_trigger(conn_id, &row.slug, cfg).await?;

// after
let slug = row.slug.trim();
if slug.is_empty() {
    anyhow::bail!("trigger row {} has no slug", row.id);
}
client.enable_trigger(conn_id, slug, cfg).await?;
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: Calling enable_trigger(connection_id, "", trigger_config) — the enable action fired without a selected trigger template, or from a catalog row whose slug field failed to deserialize.

Common situations: Enable button enabled with no trigger row selected; catalog JSON shape changed so slug parses to nothing; automation definition referencing a trigger by an outdated key.

Related errors


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