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. WithTx

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Refresh the installation list via ListChannelInstallationsByWorkspace and address the current row.
  2. Verify the workspace_id parameter matches the workspace the Slack app was connected in.
  3. 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

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


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/5824951def4872fe. Report an issue: GitHub.