mastra-ai/mastra · error

Token rotation returned incomplete data

Error message

Token rotation returned incomplete data

What it means

After a successful-looking rotation response (ok:true), the client expects both token and refresh_token fields. If either is missing the response is unusable — installing a partial token would break subsequent API calls — so it throws before mutating state.

Source

Thrown at channels/slack/src/client.ts:94

    const data = (await response.json()) as {
      ok: boolean;
      error?: string;
      token?: string;
      refresh_token?: string;
    };

    if (!data.ok) {
      if (data.error === 'invalid_refresh_token') {
        throw new Error(
          'Slack refresh token is invalid. Get fresh tokens from https://api.slack.com/apps > "Your App Configuration Tokens". ' +
            'This can happen if storage was lost or the token was already used.',
        );
      }
      throw new Error(`Token rotation failed: ${data.error}`);
    }

    if (!data.token || !data.refresh_token) {
      throw new Error('Token rotation returned incomplete data');
    }

    this.#token = data.token;
    this.#refreshToken = data.refresh_token;

    if (this.#onTokenRotation) {
      await this.#onTokenRotation({
        token: this.#token,
        refreshToken: this.#refreshToken,
      });
    }
  }

  /**
   * Create a new Slack app from a manifest.
   */
  async createApp(manifest: SlackAppManifest): Promise<SlackAppCredentials> {
    // Ensure tokens are fresh

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Log the raw rotation response to confirm the missing fields, then retry rotation
  2. Check for Slack API changes/changelog and update @mastra/channels-slack to the latest version
  3. Pin/verify no HTTP proxy or interceptor is mutating the response body
Defensive patterns

Strategy: try-catch

Type guard

function isCompleteRotationResponse(d: unknown): d is { token: string; refresh_token: string } {
  return typeof d === 'object' && d !== null && typeof (d as any).token === 'string' && typeof (d as any).refresh_token === 'string';
}

Try / catch

try {
  await client.rotateToken();
} catch (e) {
  if ((e as Error).message === 'Token rotation returned incomplete data') {
    logger.error('slack rotation returned incomplete body; retrying');
    await retry(() => client.rotateToken());
  } else throw e;
}

Prevention

When it happens

Trigger: Slack's rotation endpoint returns ok:true but omits token or refresh_token from the JSON body during #doRotateToken/rotateToken().

Common situations: Slack API contract/behavior changes or partial outages; unexpected response shape due to API version drift; proxies or middleware stripping response fields.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/f497ea6c5f296e1c. Report an issue: GitHub.