paperclipai/paperclip · error

Slack inventory failed: ${body.error ?? "unknown error"}

Error message

Slack inventory failed: ${body.error ?? "unknown error"}

What it means

Thrown by listSlackBotChannels when Slack's conversations.list responds with ok:false — Slack's standard envelope for a failed API call. The thrown message includes body.error (Slack's machine-readable error code like 'invalid_auth', 'missing_scope', 'ratelimited') or 'unknown error' if absent. Only channels where the bot is an active member are listed, so this error concerns the API call itself, not the filtering.

Source

Thrown at server/src/services/chat-provider-inventory.ts:92

    const response = await input.fetch(url, {
      headers: { authorization: `Bearer ${input.botToken}` },
      signal: slackRequestSignal(),
    });
    const body = await jsonResponse<{
      ok?: boolean;
      error?: string;
      channels?: Array<{
        id?: string;
        name?: string;
        is_member?: boolean;
        is_private?: boolean;
        is_archived?: boolean;
        context_team_id?: string;
      }>;
      response_metadata?: { next_cursor?: string };
    }>(response, "Slack");
    if (!body.ok)
      throw new Error(
        `Slack inventory failed: ${body.error ?? "unknown error"}`,
      );
    for (const channel of body.channels ?? []) {
      if (!channel.id || !channel.is_member || channel.is_archived) continue;
      resources.push({
        providerResourceId: channel.id,
        type: "channel",
        label: channel.name ? `#${channel.name}` : channel.id,
        metadata: {
          private: channel.is_private === true,
          ...(channel.context_team_id
            ? { contextTeamId: channel.context_team_id }
            : {}),
          source: "provider_inventory",
        },
      });
    }
    cursor = body.response_metadata?.next_cursor?.trim() ?? "";

View on GitHub (pinned to 01ad858492)

Solutions

  1. Read the Slack error code in the message and act on it (invalid_auth -> reconnect, missing_scope -> reinstall with scopes, ratelimited -> back off).
  2. Reconnect the Slack connection to refresh the bot token if invalid_auth.
  3. Reinstall the Slack app requesting channels:read and groups:read bot scopes if missing_scope.
  4. Add exponential backoff / reduce request frequency if ratelimited.
  5. Check Slack API status for incidents.
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate token + scopes before calling conversations.list:
const auth = await fetch('https://slack.com/api/auth.test', {
  method: 'POST', headers: { Authorization: `Bearer ${botToken}` },
}).then(r => r.json());
if (!auth.ok) throw new Error(`Slack token invalid: ${auth.error}`);

Type guard

function isSlackOkBody<T>(b: T & { ok?: boolean }): b is T & { ok: true } {
  return (b as { ok?: boolean }).ok === true;
}

Try / catch

try { const channels = await listSlackBotChannels(input); }
catch (e) {
  const err = /Slack inventory failed: (\S+)/.exec(e.message)?.[1];
  if (err === 'ratelimited') await sleep(backoff);
  else if (err === 'invalid_auth') await reconnectSlack();
  else if (err === 'missing_scope') await reinstallSlackApp(['channels:read','groups:read']);
}

Prevention

When it happens

Trigger: Slack conversations.list returns {ok:false,...}: invalid_auth (bad/expired bot token), missing_scope (bot lacks channels:read/groups:read), ratelimited, or any other Slack error code.

Common situations: Bot token rotated or revoked by a Slack admin; app reinstalled without read scopes; bulk inventory scans triggering Slack's tier-based rate limits; workspace app restrictions.

Related errors


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