paperclipai/paperclip · error · ToolGatewayHttpError

github_tool_unavailable

github_tool_unavailable

Error message

This GitHub tool is unavailable for the responsible person

What it means

After an identity grant is selected, the gateway looks for a connected tool row matching the grant's connection, the requested upstreamToolName, and providerType. If none exists, the specific GitHub tool is not available to the responsible person's selected identity, so dispatch is refused with HTTP 404 github_tool_unavailable.

Source

Thrown at server/src/services/tool-gateway.ts:2086

      throw new ToolGatewayHttpError(404, `Tool "${toolName}" not found`, "tool_not_found", { tool: toolName });
    }
    if (session.identityContextId && session.agentId && tool.connectionId) {
      const [connection] = await db.select().from(toolConnections).where(and(
        eq(toolConnections.id, tool.connectionId), eq(toolConnections.companyId, session.companyId),
      ));
      if (connection?.config.sourceTemplateKey === "github" || connection?.transportConfig?.sourceTemplateKey === "github") {
        let selected = await resolveManagedGitHubIdentitySelection(db, session.companyId, {
          agentId: session.agentId, responsibleUserId: session.responsibleUserId, allowStandingDelegation: false,
        });
        if (!selected.grant) throw new ToolGatewayHttpError(409, selected.error ?? "No GitHub identity connected", "github_identity_unavailable");
        const original = selected.grant;
        // Acquire before policy evaluation or dispatch. An alternate connection
        // gets its own catalog descriptor and policy checks; never replay a call.
        for (let attempt = 0; attempt < 2; attempt += 1) {
          const grant = selected.grant!;
          const target = connectedTools.find((candidate) => candidate.connectionId === grant.connectionId
            && candidate.upstreamToolName === tool.upstreamToolName && candidate.providerType === tool.providerType);
          if (!target) throw new ToolGatewayHttpError(404, "This GitHub tool is unavailable for the responsible person", "github_tool_unavailable");
          const [selectedConnection] = await db.select().from(toolConnections).where(and(
            eq(toolConnections.id, grant.connectionId), eq(toolConnections.companyId, session.companyId),
          ));
          if (!selectedConnection) throw new ToolGatewayHttpError(409, "GitHub connection is unavailable", "github_identity_unavailable");
          if (attempt === 0) await resolveConnectionGrant(session, selectedConnection);
          try {
            const headers = await resolveCredentialHeaders(session, selectedConnection, grant);
            githubOperationCredentials.set(session, { grant, headers });
            return target;
          } catch (error) {
            if (attempt !== 0) throw error;
            const alternate = await resolveManagedGitHubIdentitySelection(db, session.companyId, {
              agentId: session.agentId, responsibleUserId: session.responsibleUserId,
              allowStandingDelegation: false, excludeGrantId: original.id,
            });
            const accountId = original.providerTenant?.github?.userId;
            if (!accountId || !alternate.grant
              || alternate.grant.providerTenant?.github?.userId !== accountId

View on GitHub (pinned to 01ad858492)

Solutions

  1. List the connectedTools for grant.connectionId and confirm the upstreamToolName/providerType exist for that identity's connection.
  2. Use a tool name supported by the selected identity's GitHub connection; fall back to the original connection if the alternate lacks the tool.
  3. Refresh the connection's tool catalog/descriptor so newly supported GitHub tools appear.
  4. Check for upstream renames (e.g. tool renamed between GitHub app versions) and update the requested name.

Example fix

// before
await gateway.call(session, "github_create_gist", args); // 404 if unavailable for this identity
// after
const available = connectedTools.some(t => t.upstreamToolName === "github_create_gist" && t.providerType === provider);
if (!available) throw new Error("github_create_gist not available on the selected GitHub connection");
await gateway.call(session, "github_create_gist", args);
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Retry loop (attempt 0 or 1) where selected.grant.connectionId points at a connection whose catalog has no matching connectedTools entry with identical upstreamToolName and providerType — e.g. the alternate identity's connection doesn't expose that tool, the tool name changed upstream, or the tool was removed from the connection's descriptor.

Common situations: Calling a GitHub tool that exists on one connection but not the alternate identity's connection; a GitHub app scopes/tools changed; typo'd or renamed upstream tool name; providerType mismatch after adapter updates.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/ebf5718f6b2ada1f. Report an issue: GitHub.