{"record":{"id":"6cdd891ad4f637a9","repo":"chenhg5/cc-connect","slug":"relay-project-q-is-not-bound-in-this-chat-avail","errorCode":null,"errorMessage":"relay: project %q is not bound in this chat. Available targets: %s (use the exact name)","messagePattern":"relay: project %q is not bound in this chat\\. Available targets: (.+?) \\(use the exact name\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/relay.go","lineNumber":228,"sourceCode":"\n\trm.mu.RLock()\n\tbinding := rm.bindings[chatID]\n\ttargetEngine := rm.engines[req.To]\n\tsourceEngine := rm.engines[req.From]\n\tvisibility := rm.visibility\n\trm.mu.RUnlock()\n\n\tif binding == nil {\n\t\treturn nil, fmt.Errorf(\"relay: no binding for this chat. Use /bind <project> first\")\n\t}\n\tif _, ok := binding.Bots[req.To]; !ok {\n\t\tvar bound []string\n\t\tfor proj := range binding.Bots {\n\t\t\tif proj != req.From {\n\t\t\t\tbound = append(bound, proj)\n\t\t\t}\n\t\t}\n\t\treturn nil, fmt.Errorf(\"relay: project %q is not bound in this chat. Available targets: %s (use the exact name)\", req.To, strings.Join(bound, \", \"))\n\t}\n\tif targetEngine == nil {\n\t\treturn nil, fmt.Errorf(\"relay: target engine %q not found (is the project running?)\", req.To)\n\t}\n\n\tfromName := req.From\n\tif binding.Bots[req.From] != \"\" {\n\t\tfromName = binding.Bots[req.From]\n\t}\n\ttoName := req.To\n\tif binding.Bots[req.To] != \"\" {\n\t\ttoName = binding.Bots[req.To]\n\t}\n\n\t// Post the forwarded message to the group chat for visibility.  The\n\t// default target is \"<platform>:<chatID>:relay\"; platforms that\n\t// understand thread / topic semantics can override this by\n\t// implementing core.RelayGroupVisibilityTarget on their Platform impl.","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/relay.go#L210-L246","documentation":"Thrown by RelayManager.Send when a binding exists for the chat but binding.Bots has no entry for req.To. The error lists the other bound project names so the caller can correct the target name. Bot map keys are exact project names, so near-matches fail.","triggerScenarios":"RelayRequest.To is misspelled, uses a display/bot name instead of the project name, refers to a project bound in a different chat, or the target project was unbound after /bind. Any To not present in binding.Bots triggers it.","commonSituations":"Typing /to ProjB when the bound name is projb; using the bot's display name rather than the registered project name; referencing a project that is bound in another chat but not this one; stale autocomplete after rebinding.","solutions":["Use one of the project names listed in 'Available targets' exactly (case-sensitive)","Re-run /bind in this chat to add the target project to the binding","Check config.toml for the project's registered name (the engine name), not the bot display name","If the target was recently unbound, rebind it and retry"],"exampleFix":"// before: display name instead of project name\nrm.Send(ctx, core.RelayRequest{From: \"frontend\", To: \"Backend Bot\", SessionKey: key, Message: \"hi\"})\n// after: exact bound project name\nrm.Send(ctx, core.RelayRequest{From: \"frontend\", To: \"backend\", SessionKey: key, Message: \"hi\"})","handlingStrategy":"validation","validationCode":"func canRelayTo(binding *core.RelayBinding, to string) bool {\n\t_, ok := binding.Bots[to]\n\treturn ok\n}\n// surface binding.Bots keys (minus the source) to the user before sending","typeGuard":"targets := make([]string, 0, len(binding.Bots))\nfor proj := range binding.Bots { if proj != req.From { targets = append(targets, proj) } }\nif !slices.Contains(targets, req.To) { return fmt.Errorf(\"%q not bound; valid: %v\", req.To, targets) }","tryCatchPattern":"resp, err := rm.Send(ctx, req)\nif err != nil {\n\tvar avail string\n\tif _, gerr := fmt.Sscanf(err.Error(), \"relay: project %q is not bound\", new(string)); gerr == nil || strings.Contains(err.Error(), \"Available targets\") {\n\t\treply(\"Unknown target. \" + err.Error())\n\t\treturn\n\t}\n\treturn err\n}","preventionTips":["Use exact project names from config, not bot display names","Provide tab-completion or a /targets command listing bound projects","Re-check bindings after any /bind or /unbind"],"tags":["relay","binding","invalid-identifier"],"backgroundTag":"entity-not-found","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}