Skip to content

Composio direct mode surfaces entity-id mismatch as an opaque HTTP 400 with the response body discarded #5731

Closed

Description

@nocstah

Summary

In Composio direct mode, an entity-id mismatch on action execution surfaces as a bare Composio direct request failed with HTTP 400 Bad Request — the response body, which contains Composio's precise error and its suggested fix, is discarded. Users have no way to discover the actual problem.

Problem

What happened vs expected: with a Gmail connection created through Composio's own dashboard, every execute/sync fails 400. The direct client (vendor/tinymemory/core/src/sync/pipelines/composio/client.rs, execute_direct) does let _ = response.bytes().await; before bailing with just the status line. The discarded body was:

{"error":{"message":"Connected account user ID does not match the provided user ID. …","code":1812,
 "slug":"ActionExecute_ConnectedAccountEntityIdMismatch","status":400,
 "suggested_fix":"The connected_account_id you provided belongs to a different entity. …"}}

Root cause of the mismatch itself: [composio] entity_id defaults to "default", but connections created via Composio's dashboard are filed under a generated user id (pg-test-<uuid> in my case). The app sends both user_id: "default" and the connected_account_id → guaranteed 400 for any dashboard-connected account, presented as an opaque failure.

Steps to reproduce:

  1. Direct mode with your own Composio API key; leave entity_id = "default".
  2. Connect Gmail via Composio's dashboard (Connect New → OAuth), not via the app.
  3. Trigger any action/sync → opaque HTTP 400 Bad Request in logs; sync retries forever.
  4. Same request replayed with the connection's actual user_id succeeds.

Version/platform: v0.63.14, macOS, direct mode.

Solution (optional)

Two independent improvements:

  1. Surface the body — include (redacted) error.message/slug/suggested_fix in the bail message instead of discarding the bytes. Turns a dead end into a self-explanatory fix.
  2. Stop guessing the entity — the app already knows the connected_account_id; it can resolve that account's user_id from /connected_accounts (it lists them elsewhere) and use it for execute, or validate/heal entity_id at connect time, instead of requiring the config value to match by luck.

Workaround: set [composio] entity_id to the connection's user_id (visible via GET /api/v3/connected_accounts).

Acceptance criteria

  • Repro gone — a dashboard-created connection either works out of the box (entity resolved from the account) or fails with Composio's actual message including the suggested fix.
  • Regression safety — a test pins that a non-2xx direct response propagates the body's error message.
  • Diff coverage ≥ 80% — the fix PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/ci-lite.yml).

Related

—

Activity

  1. senamakel commented on Oct 9, 2026

    @senamakel
    Member

    Triage: valid — Current review confirms this is a concrete, in-scope engineering issue or request: “Composio direct mode surfaces entity-id mismatch as an opaque HTTP 400 with the response body discarded”. No complete resolution is evident in current main.

  2. added theissue type on Oct 9, 2026
  3. self-assigned this
    on Oct 9, 2026
  4. senamakel commented on Oct 9, 2026

    @senamakel
    Member

    I checked this against current main (17675ff). The code has moved since the report. vendor/tinymemory/core/src/sync/pipelines/composio/client.rs no longer exists. Composio direct-mode calls now go through the vendored tinyconnectors crate, pinned at ca3d5ff (v0.13.0).

    Part 1, surfacing the body: mostly done. vendor/tinyconnectors/crates/tinyconnectors/src/client/http.rs:271-306 (status_message) no longer discards a non-2xx body. It reads error.message (or a top-level message), redacts account and entity identifiers, truncates to 240 characters, and returns HTTP <status>: <message>. client/direct_read_tests.rs:124 covers this for a 400. The entity-mismatch case would now read HTTP 400: Connected account user ID does not match the provided user ID. …. Composio's slug and suggested_fix are still dropped, though, so the acceptance criterion "including the suggested fix" isn't fully met.

    Part 2, resolving the entity: not done. client/route/direct.rs:359-365 (execute) still sends the configured entity_id next to connected_account_id. A connection created in the Composio dashboard under a generated user id will still get a 400 unless [composio] entity_id is set to match.

    Both remaining pieces belong in tinyhumansai/tinyconnectors:

    • include suggested_fix in status_message, redacted and bounded the same way;
    • resolve the connected account's user_id, either on execute or at connect time.

    After that, this repo only needs to move its vendor/tinyconnectors pin. Leaving this open until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

source: externalIssue opened by an outside contributortriage: validReviewed and confirmed as a valid actionable issue

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions