{"record":{"id":"8113fc7474d2be2b","repo":"mastra-ai/mastra","slug":"app-manifest-update-failed-errordetails","errorCode":null,"errorMessage":"App manifest update failed: ${errorDetails}","messagePattern":"App manifest update failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/slack/src/client.ts","lineNumber":258,"sourceCode":"        '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\n    const data = (await response.json()) as {\n      ok: boolean;\n      error?: string;\n      errors?: Array<{ message: string; pointer: string }>;\n    };\n\n    if (!data.ok) {\n      let errorDetails = data.error ?? 'unknown_error';\n      if (data.errors?.length) {\n        errorDetails += ': ' + data.errors.map(e => `${e.pointer}: ${e.message}`).join(', ');\n      }\n      throw new Error(`App manifest update failed: ${errorDetails}`);\n    }\n  }\n\n  /**\n   * Set the app icon via undocumented apps.icon.set API.\n   */\n  async setAppIcon(appId: string, imageData: ArrayBuffer): Promise<void> {\n    await this.rotateToken();\n\n    const formData = new FormData();\n    formData.append('app_id', appId);\n    formData.append('image', new Blob([imageData], { type: 'image/png' }), 'icon.png');\n\n    const response = await fetch(`${SLACK_API_BASE}/apps.icon.set`, {\n      method: 'POST',\n      headers: {\n        Authorization: `Bearer ${this.#token}`,\n      },","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/channels/slack/src/client.ts#L240-L276","documentation":"updateApp pushes a new manifest to Slack via the app manifest API. On ok:false it builds errorDetails from data.error plus any field-level validation errors (pointer/message pairs) and throws.","triggerScenarios":"updateApp() (invoked from config drift checks like #checkConfigDrift) receives { ok: false } from Slack — manifest validation failure, invalid/insufficient app config token, or unknown error.","commonSituations":"Config drift reconciliation pushing a manifest Slack rejects (invalid field values); app config token lacking update permissions; editing channel config to values Slack disallows.","solutions":["Read errorDetails — fix the manifest fields identified by the pointer/message pairs in your channel configuration","Refresh app configuration tokens from https://api.slack.com/apps and retry the update","Align your stored channel config with a manifest that Slack accepts, then let drift check re-run"],"exampleFix":"// before\nmanifest.settings.event_subscriptions = { request_url: 'http://bad' }; // validation error\n// after\nmanifest.settings.event_subscriptions = { request_url: 'https://myapp.example.com/api/slack/events' };","handlingStrategy":"validation","validationCode":"function manifestUpdateSafe(m: SlackAppManifest): boolean {\n  return !!(m.display_information?.name && m.settings &&\n    (!m.oauth_config?.redirect_urls || m.oauth_config.redirect_urls.every(u => u.startsWith('https://'))));\n}\nif (!manifestUpdateSafe(manifest)) throw new Error('manifest will fail Slack validation');","typeGuard":null,"tryCatchPattern":"try {\n  await client.updateApp(appId, manifest);\n} catch (e) {\n  const msg = (e as Error).message;\n  if (msg.startsWith('App manifest update failed:')) {\n    // parse pointer/message details from msg, fix config, retry\n  } else throw e;\n}","preventionTips":["Fix manifest fields named in the error's pointer/message details","Refresh app configuration tokens with update permissions","Keep stored channel config aligned with a Slack-valid manifest","Roll out manifest changes incrementally"],"tags":["slack","manifest","config-drift","validation"],"backgroundTag":"slack-manifest-update-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}