charmbracelet/crush · error · ErrChannelOptInMismatch
requested channels differ from the existing workspace; chann
Error message
requested channels differ from the existing workspace; channels are an explicit opt-in and are not shared across duplicate creates
What it means
ErrChannelOptInMismatch reports that a duplicate CreateWorkspace specified a set of channels that differs from the channels the existing workspace was created with. Channels are an explicit opt-in and are deliberately not shared across duplicate creates, so an existing workspace is never silently reconfigured. Returned by CreateWorkspace.
Source
Thrown at internal/backend/backend.go:43
"github.com/charmbracelet/crush/internal/version"
"github.com/google/uuid"
)
// Common errors returned by backend operations.
var (
ErrWorkspaceNotFound = errors.New("workspace not found")
ErrLSPClientNotFound = errors.New("LSP client not found")
ErrAgentNotInitialized = errors.New("agent coordinator not initialized")
ErrPathRequired = errors.New("path is required")
ErrInvalidPermissionAction = errors.New("invalid permission action")
ErrUnknownCommand = errors.New("unknown command")
ErrInvalidClientID = errors.New("invalid client_id")
ErrClientNotAttached = errors.New("client not attached")
ErrWorkspaceClosing = errors.New("workspace closing")
ErrServerShuttingDown = errors.New("server is shutting down")
ErrServerNotIdle = errors.New("server is hosting live workspaces")
ErrClientRetired = errors.New("client has been retired")
ErrChannelOptInMismatch = errors.New("requested channels differ from the existing workspace; channels are an explicit opt-in and are not shared across duplicate creates")
)
// DefaultCreateGrace is the window in which a client must open an SSE
// stream after creating a workspace before its creation hold is
// released. Exposed as a package variable so tests can shorten it.
var DefaultCreateGrace = 30 * time.Second
// DefaultIdleShutdownDelay is how long the server stays alive after its
// last workspace is released before it shuts itself down. The delay
// exists so a client that closes one session and opens another moments
// later (the same directory or a different one) reuses the still-running
// server instead of racing its shutdown: with an immediate shutdown the
// new client can attach to — or create a workspace on — a server that is
// already tearing down, and then observe its coder agent as "offline".
// Any workspace create within the window cancels the pending shutdown.
// Overridable via CRUSH_SERVER_IDLE_TIMEOUT (seconds; 0 restores the
// old shut-down-immediately behavior).
var DefaultIdleShutdownDelay = 60 * time.SecondView on GitHub (pinned to 7944b8e522)
Solutions
- Make the duplicate create request the same channel set the existing workspace was created with
- Delete the existing workspace first, then re-create with the desired channels
- Align channel configuration across all clients that share the working directory
Example fix
// before
ws, err := backend.CreateWorkspace(ctx, id, path, backend.WithChannels("events")) // existing ws has none
// after
ws, err := backend.DeleteWorkspace(ctx, id, path)
if err != nil { return err }
ws, err = backend.CreateWorkspace(ctx, id, path, backend.WithChannels("events")) Defensive patterns
Strategy: validation
Validate before calling
if existing, ok := workspaceAt(path); ok && !slices.Equal(existing.Channels, requestedChannels) {
// either drop the channels arg to match, or delete and re-create
if err := backend.DeleteWorkspace(ctx, id, path); err != nil {
return err
}
} Type guard
func isErrChannelOptInMismatch(err error) bool {
return errors.Is(err, backend.ErrChannelOptInMismatch)
} Try / catch
ws, err := backend.CreateWorkspace(ctx, id, path, opts...)
if errors.Is(err, backend.ErrChannelOptInMismatch) {
// retry matching the existing workspace's channels
ws, err = backend.CreateWorkspace(ctx, id, path, existingChannelsOpts...)
}
return err Prevention
- Keep channel configuration in one shared config file for all clients of a directory
- Omit the channels option on duplicate creates to inherit the existing opt-in
- Delete and re-create the workspace when channel requirements genuinely change
When it happens
Trigger: Calling CreateWorkspace with the same path and client when a workspace already exists at that path, but passing a different channels set than the original create (e.g. one call opts into a channel, the other does not).
Common situations: Two launch points (editor + CLI) creating workspaces for the same directory with differing channel configurations; config change between the first and second launch adding or removing an opted-in channel; a stale script pinned to old channel flags.
Related errors
- invalid JSON in config file %s
- client not attached
- workspace closing
- not found
- agent coordinator not initialized
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/c7e8526753c2d045.
Report an issue: GitHub.