chenhg5/cc-connect · error

relay: no binding for this chat. Use /bind <project> first

Error message

relay: no binding for this chat. Use /bind <project> first

What it means

RelayManager.Send in core/relay.go throws this when the chat the request originates from has no relay binding registered in rm.bindings. A binding is created only after a user runs /bind in that chat, mapping the chat to one or more project bots. Without it, the relay manager refuses to route cross-project messages for safety.

Source

Thrown at core/relay.go:219

	Response string `json:"response"`
}

// Send delivers a message from one bot to another and returns the response.
func (rm *RelayManager) Send(ctx context.Context, req RelayRequest) (*RelayResponse, error) {
	platform, chatID, err := parseSessionKeyParts(req.SessionKey)
	if err != nil {
		return nil, fmt.Errorf("relay: invalid session key: %w", err)
	}

	rm.mu.RLock()
	binding := rm.bindings[chatID]
	targetEngine := rm.engines[req.To]
	sourceEngine := rm.engines[req.From]
	visibility := rm.visibility
	rm.mu.RUnlock()

	if binding == nil {
		return nil, fmt.Errorf("relay: no binding for this chat. Use /bind <project> first")
	}
	if _, ok := binding.Bots[req.To]; !ok {
		var bound []string
		for proj := range binding.Bots {
			if proj != req.From {
				bound = append(bound, proj)
			}
		}
		return nil, fmt.Errorf("relay: project %q is not bound in this chat. Available targets: %s (use the exact name)", req.To, strings.Join(bound, ", "))
	}
	if targetEngine == nil {
		return nil, fmt.Errorf("relay: target engine %q not found (is the project running?)", req.To)
	}

	fromName := req.From
	if binding.Bots[req.From] != "" {
		fromName = binding.Bots[req.From]
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Run /bind <project> in the chat that is issuing the relay request, then retry
  2. Verify the SessionKey's chatID (via parseSessionKeyParts: 'platform:chatID:userID' or 'relay:sourceProject:chatID') matches the chat where the binding exists
  3. Re-register the binding programmatically if driving RelayManager from code (populate rm.bindings[chatID])
  4. If the chat was migrated/recreated, re-run /bind since the old chatID no longer matches

Example fix

// before: relay sent from an unbound chat
rm.Send(ctx, core.RelayRequest{From: "proj-a", To: "proj-b", SessionKey: "feishu:oc_newchat:u1", Message: "hi"})
// after: run "/bind proj-b" in chat oc_newchat first, or use the bound chat's key
rm.Send(ctx, core.RelayRequest{From: "proj-a", To: "proj-b", SessionKey: "feishu:oc_boundchat:u1", Message: "hi"})
Defensive patterns

Strategy: validation

Validate before calling

func chatBound(rm *core.RelayManager, sessionKey string) bool {
	_, chatID, err := core.ParseSessionKeyParts(sessionKey) // or replicate SplitN(":", 3)
	if err != nil { return false }
	rm.Lock(); defer rm.Unlock()
	return rm.Bindings()[chatID] != nil
}
// only call Send when chatBound(...) is true; otherwise prompt the user to run /bind

Type guard

if binding := rm.LookupBinding(chatID); binding == nil { return fmt.Errorf("chat %s not bound; run /bind first", chatID) }

Try / catch

resp, err := rm.Send(ctx, req)
if err != nil {
	if strings.Contains(err.Error(), "no binding for this chat") {
		reply("This chat is not bound. Use /bind <project> first.")
		return
	}
	return err
}

Prevention

When it happens

Trigger: Calling rm.Send(ctx, RelayRequest{From, To, SessionKey, Message}) where parseSessionKeyParts(SessionKey) yields a chatID that is not a key in rm.bindings — i.e. /bind was never run in that chat, or the SessionKey's chatID differs from the chat where /bind was executed.

Common situations: Users send relay commands (/to <project> <msg>) in a group or DM before ever running /bind; the bot moved to a new chat (new chatID) after a group migration; the session key passed programmatically has a chatID that doesn't match the bound chat.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/eeb7f3b5b4b7ab98. Report an issue: GitHub.