multica-ai/multica · error · ErrInstallationNotFound
slack installation not found
Error message
slack installation not found
What it means
Slack ErrInstallationNotFound: no channel_installation row (channel_type='slack') matches the lookup in the given workspace. Sentinel exists so HTTP handlers return 404 without importing pgx; distinct from the ownership-collision errors raised during install.
Source
Thrown at server/internal/integrations/slack/install.go:29
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
"github.com/multica-ai/multica/server/internal/integrations/channel/engine"
"github.com/multica-ai/multica/server/internal/util/secretbox"
db "github.com/multica-ai/multica/server/pkg/db/generated"
)
// This file is the Slack install backend (MUL-3666). Slack uses the
// bring-your-own-app (BYO) model: the workspace admin creates their own Slack
// app, installs it to their Slack workspace, and pastes its bot token (xoxb-) +
// app-level token (xapp-) into Multica (the paste path lives in byo_install.go).
// The InstallService owns the at-rest encryption of those tokens — so no caller
// can write a channel_installation with a plaintext token — plus the shared
// persistInstall transaction and the list / get / revoke management surface.
var (
// ErrInstallationNotFound surfaces "no row matches in this workspace".
ErrInstallationNotFound = errors.New("slack installation not found")
// ErrTeamOwnedByAnotherWorkspace is returned when the pasted Slack app is
// already connected to a live owner in a DIFFERENT Multica workspace — it
// would collide with the (channel_type, app_id) routing index. A Slack app is
// one bot identity and maps to one agent; reusing it here requires
// disconnecting it in the other workspace first.
ErrTeamOwnedByAnotherWorkspace = errors.New("slack: this Slack app is already connected to a different Multica workspace")
// ErrTeamOwnedBySameWorkspace is returned when the app is already connected to
// a DIFFERENT (live, non-archived) agent in the SAME workspace. The old
// catch-all wrongly blamed "another workspace"; naming the same-workspace case
// points the user at the Disconnect they can actually reach (#4810).
ErrTeamOwnedBySameWorkspace = errors.New("slack: this Slack app is already connected to another agent in this workspace")
// ErrTeamOwnedByArchivedAgent is returned when the app's owning agent is
// archived (and so still holds the bot, since archiving is reversible). The
// user recovers by restoring that agent or disconnecting its bot.
ErrTeamOwnedByArchivedAgent = errors.New("slack: this Slack app is connected to an archived agent in this workspace")
)
// installQueries is the slice of generated queries InstallService needs. WithTxView on GitHub (pinned to 2c0912b6ec)
Solutions
- Refresh the installation list via ListChannelInstallationsByWorkspace and address the current row.
- Verify the workspace_id parameter matches the workspace the Slack app was connected in.
- If the app was disconnected, run the BYO connect flow again to create a new installation.
Example fix
// before
inst, err := svc.Get(ctx, workspaceID, id)
if err != nil {
return err
}
// after
inst, err := svc.Get(ctx, workspaceID, id)
if errors.Is(err, slack.ErrInstallationNotFound) {
http.NotFound(w, r)
return
} Defensive patterns
Strategy: try-catch
Validate before calling
insts, _ := installSvc.List(ctx, workspaceID)
have := false
for _, i := range insts { if i.ID == wantID { have = true } }
if !have { return refreshList(w) } Try / catch
inst, err := installSvc.Get(ctx, workspaceID, id)
if err != nil {
if errors.Is(err, slack.ErrInstallationNotFound) {
http.NotFound(w, r)
return
}
return err
} Prevention
- Invalidate cached installation ids after a disconnect anywhere in the UI.
- Refetch the installation list on focus/visibility so stale ids self-heal.
- Always pair installation id with workspace id in URLs.
When it happens
Trigger: Calling InstallService get/revoke with a (workspace_id, installation id or app id) pair with no matching row — wrong workspace, already-disconnected app, or a stale id held by the UI.
Common situations: Frontend holds a cached installation id after the admin disconnected the app in another tab; workspace-scoped lookup receives the installation's id from a different workspace; deleted/re-installed app leaves old references behind.
Related errors
- ErrInstallationNotFound
- slack: binding token invalid or expired
- slack: user id is already bound to a different user
- slack: this Slack app is already connected to a different Mu
- slack: this Slack app is already connected to another agent
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/5824951def4872fe.
Report an issue: GitHub.