chenhg5/cc-connect · error
workspace binding unavailable for source channel %q
Error message
workspace binding unavailable for source channel %q
What it means
In multi-workspace relay mode, resolveWorkspace returned an empty workspace string AND an effective workspace binding exists for the channel but is currently unusable (e.g. its directory is missing or the binding is disabled). cc-connect reports 'workspace binding unavailable for source channel %q' with the channel key. This distinguishes 'binding exists but broken' from 'no binding at all' (the sibling error).
Source
Thrown at core/engine.go:15944
func (e *Engine) relayContextForSourceSessionKey(fromProject, sourceSessionKey string) (Agent, *SessionManager, string, error) {
platformName, chatID, err := parseSessionKeyParts(sourceSessionKey)
if err != nil {
return nil, nil, "", fmt.Errorf("invalid source session key: %w", err)
}
relaySessionKey := relayConversationKey(fromProject, platformName, chatID)
if !e.multiWorkspace || e.workspaceBindings == nil {
return e.agent, e.sessions, relaySessionKey, nil
}
channelKey := workspaceChannelKey(platformName, chatID)
workspace, _, err := e.resolveWorkspace(e.platformForName(platformName), chatID)
if err != nil {
return nil, nil, "", fmt.Errorf("resolve relay workspace: %w", err)
}
if workspace == "" {
if b, _, usable := e.lookupEffectiveWorkspaceBinding(channelKey); b != nil && !usable {
return nil, nil, "", fmt.Errorf("workspace binding unavailable for source channel %q", channelKey)
}
return nil, nil, "", fmt.Errorf("no workspace binding for source channel %q", channelKey)
}
agent, sessions, err := e.getOrCreateWorkspaceAgent(workspace)
if err != nil {
return nil, nil, "", fmt.Errorf("get relay workspace agent: %w", err)
}
if ws := e.workspacePool.Get(workspace); ws != nil {
ws.Touch()
}
return agent, sessions, relaySessionKey, nil
}
// HandleRelay processes a relay message synchronously: starts or resumes a
// dedicated relay session, sends the message to the agent, and blocks until
// the complete response is collected (or the relay context times out).
func (e *Engine) HandleRelay(ctx context.Context, fromProject, sourceSessionKey, message string) (string, error) {View on GitHub (pinned to 4000b2338a)
Solutions
- Check the binding for the printed channel key in config.toml / workspace bindings store
- Verify the bound workspace path exists and is readable/writable by the cc-connect process
- Re-bind the channel to a valid workspace or remove the stale binding
- Check process user/permissions if the path exists but is inaccessible
Example fix
// before (config.toml) [[workspace_bindings]] channel = "telegram:12345678" path = "/home/user/old-project" # deleted // after [[workspace_bindings]] channel = "telegram:12345678" path = "/home/user/projects/active"
Defensive patterns
Strategy: validation
Validate before calling
// validate bindings at startup: path must exist and be writable
for _, b := range bindings {
if fi, err := os.Stat(b.Path); err != nil || !fi.IsDir() {
slog.Error("workspace binding path invalid", "channel", b.Channel, "path", b.Path)
}
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "workspace binding unavailable") {
slog.Error("binding exists but unusable; check bound path", "channel", channelKey)
}
return err
} Prevention
- Add a startup check that every bound workspace path exists and is writable
- Use stable absolute paths (or symlinks you control) for workspace bindings
- Re-validate bindings after moving/deleting project directories
- Run cc-connect under a user with consistent filesystem permissions
When it happens
Trigger: Relay targets a channel that HAS a configured workspace binding (lookupEffectiveWorkspaceBinding returns b != nil) but the binding is not usable — commonly because the bound workspace path no longer exists on disk, lacks permissions, or the binding was toggled off.
Common situations: Workspace directory deleted/renamed/moved after binding was configured; insufficient filesystem permissions after running under a different user; binding defined for a channel the workspace no longer serves.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- no workspace binding for source channel %q
- relay: no binding for this chat. Use /bind <project> first
- resolve relay workspace: %w
- get relay workspace agent: %w
- relay: project %q is not bound in this chat. Available targe
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/a834b2560fe9f1f2.
Report an issue: GitHub.