tinyhumansai/openhuman · error · anyhow::Error
composio direct authorize: toolkit must not be empty
Error message
composio direct authorize: toolkit must not be empty
What it means
direct_authorize (the direct-mode, non-backend-proxied authorize) rejects a toolkit name that is empty after trimming before requesting a hosted connect URL. It mirrors the backend-proxied authorize guard; an empty entity_id is tolerated and defaults to "default", but the toolkit is mandatory.
Source
Thrown at src/openhuman/integrations/composio/client.rs:891
/// reshapes the response into the [`ComposioAuthorizeResponse`] the
/// backend-proxied path emits.
///
/// The v3 endpoint returns a redirect URL but does NOT (currently)
/// surface a stable `connection_id` in the same call — the connection
/// row is created lazily when the user completes OAuth on Composio's
/// hosted page. To preserve the response contract the frontend already
/// consumes, we emit an empty `connection_id` for now. The 5 s
/// `list_connections` poll (now live in direct mode too — see
/// [`direct_list_connections`]) is what ultimately surfaces the new
/// row to the UI.
pub(super) async fn direct_authorize(
direct: &Arc<crate::openhuman::tools::ComposioTool>,
toolkit: &str,
entity_id: &str,
) -> anyhow::Result<ComposioAuthorizeResponse> {
let toolkit = toolkit.trim();
if toolkit.is_empty() {
anyhow::bail!("composio direct authorize: toolkit must not be empty");
}
let entity_id = entity_id.trim();
let entity_id = if entity_id.is_empty() {
"default"
} else {
entity_id
};
tracing::debug!(
toolkit = %toolkit,
entity_id = %entity_id,
"[composio-direct] authorize: requesting hosted connect URL"
);
let connect_url = direct
.get_connection_url(Some(toolkit), None, entity_id)
.await?;
tracing::debug!(
toolkit = %toolkit,
url_len = connect_url.len(),View on GitHub (pinned to 7491200858)
Solutions
- Enforce toolkit selection before the authorize action is reachable
- Trim and validate the toolkit id at the boundary and fail with UI-friendly context
- Cross-check the toolkit against the direct-mode catalog when one is available
Example fix
// before
let resp = direct_authorize(&tool, toolkit_param, entity).await?;
// after
let toolkit = toolkit_param.trim();
if toolkit.is_empty() {
return Err(anyhow::anyhow!("toolkit is required to start a direct authorize"));
}
let resp = direct_authorize(&tool, toolkit, entity).await?; Defensive patterns
Strategy: validation
Validate before calling
let toolkit = toolkit.trim();
if toolkit.is_empty() {
anyhow::bail!("toolkit is required for direct composio authorize");
}
let resp = direct_authorize(&direct_tool, toolkit, entity_id).await?; Type guard
fn is_non_empty_toolkit(s: &str) -> bool {
!s.trim().is_empty()
} Prevention
- Reuse the same toolkit validation for proxied and direct authorize paths
- Filter blank entries when batch-authorizing toolkits from a list
- Make toolkit a required request field in the RPC schema so the boundary rejects it first
When it happens
Trigger: Calling direct_authorize(&direct_tool, "", entity_id) in direct mode — same producer bugs as the proxied path: unselected toolkit in the connection UI, or a missing config key.
Common situations: Direct-mode connection form submitted without a toolkit; toolkit id sourced from a renamed config field; scripted bulk-authorize iterating an incomplete toolkit list.
Related errors
- composio.authorize: toolkit must not be empty
- composio direct_execute: tool slug must not be empty
- composio.execute_tool: tool slug must not be empty
- composio.authorize: extra_params cannot override reserved ke
- composio.delete_connection: connectionId must not be empty
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/a19b78ba4f1f7382.
Report an issue: GitHub.