{"record":{"id":"e34ce8d3b0229a58","repo":"mastra-ai/mastra","slug":"failed-to-check-whether-slack-app-exists-data-e","errorCode":null,"errorMessage":"Failed to check whether Slack app exists: ${data.error ?? 'unknown_error'}","messagePattern":"Failed to check whether Slack app exists: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/slack/src/client.ts","lineNumber":228,"sourceCode":"    });\n\n    const data = (await response.json()) as {\n      ok: boolean;\n      error?: string;\n    };\n\n    if (data.ok) return true;\n\n    // Only a definitive \"app is gone\" answer counts as non-existence. Slack\n    // returns `app_not_found` when the app was deleted and `invalid_app_id`\n    // when the id is malformed. Any other error (rate limiting, auth, outage)\n    // is transient — re-throw so callers don't tear down a valid installation\n    // on a temporary failure.\n    if (data.error === 'app_not_found' || data.error === 'invalid_app_id') {\n      return false;\n    }\n\n    throw new Error(`Failed to check whether Slack app exists: ${data.error ?? 'unknown_error'}`);\n  }\n\n  /**\n   * Update an existing Slack app's manifest.\n   */\n  async updateApp(appId: string, manifest: SlackAppManifest): Promise<void> {\n    await this.rotateToken();\n\n    const response = await fetch(`${SLACK_API_BASE}/apps.manifest.update`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Authorization: `Bearer ${this.#token}`,\n      },\n      body: JSON.stringify({ app_id: appId, manifest }),\n      signal: AbortSignal.timeout(SLACK_API_TIMEOUT_MS),\n    });\n","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/channels/slack/src/client.ts#L210-L246","documentation":"appExists checks whether the Slack app still exists. It returns false for the expected 'not found' errors (app_not_found, invalid_app_id) but any OTHER error is unexpected — it could be transient — so the client re-throws rather than reporting false, preventing callers from tearing down a valid installation on a temporary failure.","triggerScenarios":"appExists() (called from connect) receives { ok: false, error: X } where X is neither app_not_found nor invalid_app_id — e.g. fatal_error, invalid_auth, rateLimited, network-level issues surfaced as Slack errors.","commonSituations":"Slack API outage or rate limiting during channel connect; bad/expired app configuration token; intermittent network failures in deployment environments.","solutions":["Retry the connect/appExists call after a short backoff — the error is often transient","Verify app configuration tokens are valid (invalid_auth → get fresh tokens from the Slack app config)","Check Slack's status page if errors persist, and only treat the app as missing when appExists returns false"],"exampleFix":"// before\nconst exists = await client.appExists(appId); // throws on transient error\n// after\nlet exists: boolean;\ntry { exists = await client.appExists(appId); }\ncatch (e) { exists = true; /* assume exists; don't tear down on transient failure */ }","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let exists: boolean;\ntry {\n  exists = await client.appExists(appId);\n} catch (e) {\n  // transient failure: assume the app exists rather than tearing down a valid install\n  logger.warn({ err: e }, 'appExists check failed; assuming exists');\n  exists = true;\n}","preventionTips":["Never treat a thrown appExists error as 'app missing'","Add backoff/retry around connect flows","Refresh app configuration tokens when invalid_auth appears","Distinguish the safe false return (app_not_found/invalid_app_id) from thrown errors"],"tags":["slack","api","transient","availability"],"backgroundTag":"slack-app-exists-check-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}