Budibase/budibase · error · HTTPError
Slack app configuration token has expired. Save a new config
Error message
Slack app configuration token has expired. Save a new config token and refresh token.
What it means
This HTTP 400 error is thrown by assertSlackOk when a Slack API response returns ok:false with error 'token_expired'. Budibase uses Slack app configuration tokens (app config tokens with refresh tokens) for manifest-based app creation; these tokens expire and must be rotated. The message instructs you to save a new config token and refresh token pair.
Source
Thrown at packages/server/src/sdk/workspace/ai/deployments/slack.ts:175
name?: string
}
}
interface SlackConfigTokenRotateResponse extends SlackApiResponse {
token?: string
refresh_token?: string
exp?: number
}
const assertSlackOk = <T extends SlackApiResponse>(
payload: T,
action: string
) => {
if (payload.ok) {
return payload
}
if (payload.error === "token_expired") {
throw new HTTPError(
"Slack app configuration token has expired. Save a new config token and refresh token.",
400
)
}
if (payload.error === "invalid_refresh_token") {
throw new HTTPError(
"Slack app configuration refresh token is invalid. Save a new config token and refresh token.",
400
)
}
const details = payload.errors?.map(error => error.message).filter(Boolean)
const message = details?.length
? `${action}: ${details.join(", ")}`
: `${action}: ${payload.error || "unknown_error"}`
throw new HTTPError(message, 400)
}
export const createSlackAppFromManifest = async ({View on GitHub (pinned to a81a902e9a)
Solutions
- Obtain a fresh Slack app configuration token and refresh token from the Slack app setup flow, then save both via the agent's Slack integration settings.
- Call rotateSlackConfigToken with a valid refresh token to mint a new access token before retrying the operation.
- Re-run the Slack OAuth/app-manifest setup from the Budibase UI to regenerate tokens end-to-end.
- If refresh also fails with invalid_refresh_token, restart the full Slack app setup (see error 495).
Example fix
// before
await createSlackAppFromManifest({ configToken: staleToken, manifest }) // token_expired
// after
const rotated = await rotateSlackConfigToken({ refreshToken: storedRefreshToken })
await createSlackAppFromManifest({ configToken: rotated.configToken, manifest }) Defensive patterns
Strategy: try-catch
Try / catch
try {
await createSlackAppFromManifest({ configToken, manifest })
} catch (e) {
if (e instanceof HTTPError && e.message.includes("token has expired")) {
const rotated = await rotateSlackConfigToken({ refreshToken })
await createSlackAppFromManifest({ configToken: rotated.configToken, manifest })
} else throw e
} Prevention
- Rotate the Slack config token proactively (tokens are short-lived) before long-running deploy operations.
- Always persist the new config + refresh token pair returned by each rotation.
- Timestamp stored tokens and prompt for re-setup when they age past the known lifetime.
When it happens
Trigger: Calling createSlackAppFromManifest, exchangeSlackOAuthCode, or rotated() with a Slack configuration access token that Slack has expired - e.g. deploying/creating a Slack app with a config token captured hours/days earlier that has since expired.
Common situations: Config token stored in the agent/environment long ago and never refreshed; token rotation failed silently in a previous run; a stale token was copied from old documentation or a teammate's expired setup.
Related errors
- Slack app creation response was incomplete
- Slack OAuth callback is missing state
- Slack OAuth state is invalid or expired
- Slack OAuth authorization failed
- Slack OAuth callback is missing the authorization code
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/42da8cef2cc2575e.
Report an issue: GitHub.