multica-ai/multica · error
not a member of this workspace
Error message
not a member of this workspace
What it means
Generic membership guard in HandleWebSocket's HTTP upgrade path: after authenticating the session cookie via authenticateToken, the server checks mc.IsMember for the requested workspace before issuing the WebSocket connection. It returns this sentinel 403 body when the authenticated userID has no membership record for the workspace identified by workspace_id/workspace_slug — i.e. a valid, logged-in user attempting to open a realtime socket for a workspace they do not belong to (wrong workspace, revoked/removed membership, or a slug pointing at another org's workspace).
Solutions
- Join the workspace first, or connect with an account that is a member.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/internal/realtime/hub.go:793 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/8b0ac6e73980f1ff.
Report an issue: GitHub.
Appendix: source
Thrown at server/internal/realtime/hub.go:793
return
}
workspaceID = resolved
}
}
if workspaceID == "" {
http.Error(w, `{"error":"workspace_id or workspace_slug required"}`, http.StatusBadRequest)
return
}
var userID string
if cookie, err := r.Cookie(auth.AuthCookieName); err == nil && cookie.Value != "" {
uid, errMsg := authenticateToken(cookie.Value, pr, r.Context())
if errMsg != "" {
http.Error(w, errMsg, http.StatusUnauthorized)
return
}
if !mc.IsMember(r.Context(), uid, workspaceID) {
http.Error(w, `{"error":"not a member of this workspace"}`, http.StatusForbidden)
return
}
userID = uid
}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
slog.Error("websocket upgrade failed", "error", err)
return
}
// Bound inbound messages here rather than in readPump: the token auth
// path below reads its first frame before the caller is authenticated, so
// a limit installed any later leaves that read unbounded.
conn.SetReadLimit(inboundReadLimit)
if userID == "" {
tokenStr, errMsg, closed := firstMessageAuth(conn)View on GitHub (pinned to 2c0912b6ec)