{"record":{"id":"966aa204f644750d","repo":"Budibase/budibase","slug":"failed-to-create-slack-app","errorCode":null,"errorMessage":"Failed to create Slack app","messagePattern":"Failed to create Slack app","errorType":"http","errorClass":"HTTPError","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/deployments/slack.ts","lineNumber":212,"sourceCode":"  configToken,\n  manifest,\n}: {\n  configToken: string\n  manifest: ReturnType<typeof buildSlackManifest>\n}) => {\n  const response = await fetch(`${SLACK_API_BASE}/apps.manifest.create`, {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Authorization: `Bearer ${configToken}`,\n    },\n    body: JSON.stringify({\n      manifest: JSON.stringify(manifest),\n    }),\n  })\n  const payload = (await response.json()) as SlackManifestCreateResponse\n  if (!response.ok) {\n    throw new HTTPError(\"Failed to create Slack app\", response.status)\n  }\n  return assertSlackOk(payload, \"Failed to create Slack app\")\n}\n\nexport const exchangeSlackOAuthCode = async ({\n  code,\n  clientId,\n  clientSecret,\n  redirectUri,\n}: {\n  code: string\n  clientId: string\n  clientSecret: string\n  redirectUri: string\n}) => {\n  const response = await fetch(`${SLACK_API_BASE}/oauth.v2.access`, {\n    method: \"POST\",\n    headers: {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/deployments/slack.ts#L194-L230","documentation":"This error is thrown by createSlackAppFromManifest when the HTTP response from Slack's app manifest creation endpoint has a non-ok status. It is a transport/HTTP-level failure distinct from the API-level ok:false handling done by assertSlackOk, and preserves Slack's HTTP status code. It indicates the request to create the Slack app never produced a parseable successful response.","triggerScenarios":"POSTing a manifest to Slack's api.slack.com app-manifest create endpoint and receiving 4xx/5xx - e.g. 401/403 from an invalid config token header, 429 rate limit, 5xx Slack outage, or a network/proxy returning a non-2xx status.","commonSituations":"Expired/invalid Slack config token used as bearer auth; Slack API incident; corporate proxy intercepting the call; malformed JSON body causing a 400 before Slack parses the manifest.","solutions":["Check the HTTP status (included in the error) - 401/403 means refresh the Slack config token; 429 means back off and retry.","Verify the Slack API status page / retry later if the status is 5xx (Slack outage).","Confirm the outbound network path allows HTTPS to api.slack.com from the Budibase server/worker.","Re-obtain the config token via the Slack setup flow and retry the manifest creation."],"exampleFix":"// before - one-shot call with no handling\nawait createSlackAppFromManifest({ configToken, manifest })\n// after - handle status-specific recovery\ntry {\n  await createSlackAppFromManifest({ configToken, manifest })\n} catch (e) {\n  if (String(e.status) === \"429\") await sleep(30000) // then retry\n  else throw e\n}","handlingStrategy":"retry","validationCode":"const configToken = process.env.SLACK_CONFIG_TOKEN\nif (!configToken) throw new Error(\"SLACK_CONFIG_TOKEN must be set before creating a Slack app\")","typeGuard":null,"tryCatchPattern":"try {\n  await createSlackAppFromManifest({ configToken, manifest })\n} catch (e) {\n  if (e instanceof HTTPError && e.status === 429) {\n    await sleep(30000)\n    return createSlackAppFromManifest({ configToken, manifest }) // single retry\n  }\n  if (e instanceof HTTPError && e.status === 401) {\n    // rotate/refresh the config token before retrying\n  }\n  throw e\n}","preventionTips":["Retry with backoff on 5xx/429; do not blindly retry 4xx auth failures.","Check Slack's status page when seeing persistent 5xx.","Ensure server egress to api.slack.com is allowed (firewall/proxy)."],"tags":["slack","http","network","api-error"],"backgroundTag":"upstream-http-error","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}