multica-ai/multica · error · ErrTokenAppMismatch
slack: the bot token and app-level token are from different
Error message
slack: the bot token and app-level token are from different Slack apps
What it means
Slack BYO validation error: the pasted xoxb- bot token and xapp- app-level token belong to DIFFERENT Slack apps. Persisting such a pair would appear connected but be broken: inbound events arrive over the app token's Socket Mode connection (routed by its app id) while mention detection and outbound posting use the bot token's identity.
Source
Thrown at server/internal/integrations/slack/byo_install.go:29
"github.com/jackc/pgx/v5/pgtype"
"github.com/slack-go/slack"
db "github.com/multica-ai/multica/server/pkg/db/generated"
)
// ErrInvalidBotToken / ErrInvalidAppToken are returned by RegisterBYO when a
// pasted token is malformed (wrong prefix, or an app token whose app id cannot
// be parsed). The handler maps them to 400 so the dialog can show a precise hint
// instead of a generic failure.
var (
ErrInvalidBotToken = errors.New("slack: bot token must start with xoxb-")
ErrInvalidAppToken = errors.New("slack: app-level token must start with xapp- and embed an app id")
// ErrTokenAppMismatch is returned when the pasted bot token and app-level
// token belong to DIFFERENT Slack apps. Persisting that pair would "connect"
// but be broken: inbound arrives on the app token's socket (routed by its
// app id) while mention detection + outbound use the bot token's identity.
ErrTokenAppMismatch = errors.New("slack: the bot token and app-level token are from different Slack apps")
)
// RegisterBYOParams are the inputs for a bring-your-own-app install: the agent
// this bot represents, who is installing, and the two tokens the user pasted
// from their own Slack app.
type RegisterBYOParams struct {
WorkspaceID pgtype.UUID
AgentID pgtype.UUID
InitiatorID pgtype.UUID
BotToken string // xoxb-… — outbound Web API (chat.postMessage)
AppToken string // xapp-… — this app's OWN Socket Mode connection (inbound)
}
// RegisterBYO installs a user-supplied ("bring your own") Slack app for an agent.
// The user creates their own Slack app, installs it to their workspace, and
// pastes its bot token (xoxb-) + app-level token (xapp-). There is NO OAuth code
// exchange: we validate the bot token live via auth.test (which also yields the
// team id + bot user id), prove the bot + app tokens belong to the SAME app,View on GitHub (pinned to 2c0912b6ec)
Solutions
- Open ONE Slack app's configuration and copy both tokens from that same app: Bot User OAuth Token (xoxb-) from OAuth & Permissions and App-Level Token (xapp-) from Basic Information.
- Delete the stale/duplicate app if it exists, so only one candidate remains to copy from.
- After re-copying, re-run RegisterBYO; the mismatch check passes only when both tokens embed the same app id.
Example fix
// before
params.BotToken = "xoxb-..." // app A
params.AppToken = "xapp-..." // app B
err := svc.RegisterBYO(ctx, params)
// -> "slack: the bot token and app-level token are from different Slack apps"
// after: pre-validate app id alignment in the handler
botAppID, appAppID := parseAppID(params.BotToken), parseAppID(params.AppToken)
if botAppID != "" && appAppID != "" && botAppID != appAppID {
return respondError(w, 400, "both tokens must come from the same Slack app")
}
err := svc.RegisterBYO(ctx, params) Defensive patterns
Strategy: validation
Validate before calling
botApp := appIDFromToken(params.BotToken) // parses app id from xoxb- token
appApp := appIDFromToken(params.AppToken) // parses app id from xapp- token
if botApp != "" && appApp != "" && botApp != appApp {
return respondError(w, 400, "both tokens must come from the same Slack app")
}
_ = svc.RegisterBYO(ctx, params) Try / catch
if err := svc.RegisterBYO(ctx, params); err != nil {
if errors.Is(err, slack.ErrTokenAppMismatch) {
return respondError(w, 400, "bot token and app token are from different apps — copy both from ONE app")
}
return err
} Prevention
- Copy both tokens in one sitting from one app's pages, in one browser tab.
- Delete abandoned half-configured Slack apps so only one candidate exists to copy from.
- Remember the failure mode this prevents: a mismatched pair 'connects' but inbound and outbound use different identities.
When it happens
Trigger: Calling RegisterBYO where the app id embedded in the xapp- token does not match the app id of the xoxb- bot token — e.g. the admin created two Slack apps and copied the bot token from one and the app-level token from the other.
Common situations: Two similarly named apps in the Slack dashboard; regenerated tokens in a new app after following an outdated tutorial; copy/paste mix-up between browser tabs each open to a different app's credentials page.
Related errors
- slack: bot token must start with xoxb-
- slack: this Slack app is already connected to a different Mu
- slack: this Slack app is already connected to another agent
- slack: this Slack app is connected to an archived agent in t
- cloud runtime fleet URL is not configured
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/77ce86efeb928154.
Report an issue: GitHub.