{"record":{"id":"65cf77e62d49b82c","repo":"chenhg5/cc-connect","slug":"relay-invalid-session-key-w","errorCode":null,"errorMessage":"relay: invalid session key: %w","messagePattern":"relay: invalid session key: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/relay.go","lineNumber":208,"sourceCode":"\n// RelayRequest is the payload for a relay send.\ntype RelayRequest struct {\n\tFrom       string `json:\"from\"`        // source project name\n\tTo         string `json:\"to\"`          // target project name\n\tSessionKey string `json:\"session_key\"` // source session key (contains platform + chatID)\n\tMessage    string `json:\"message\"`\n}\n\n// RelayResponse is the result of a relay send.\ntype RelayResponse struct {\n\tResponse string `json:\"response\"`\n}\n\n// Send delivers a message from one bot to another and returns the response.\nfunc (rm *RelayManager) Send(ctx context.Context, req RelayRequest) (*RelayResponse, error) {\n\tplatform, chatID, err := parseSessionKeyParts(req.SessionKey)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"relay: invalid session key: %w\", err)\n\t}\n\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}","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/relay.go#L190-L226","documentation":"RelayManager.Send parses req.SessionKey into platform and chatID parts via parseSessionKeyParts; a malformed key aborts the send, wrapping the underlying parse error with the 'relay: invalid session key' prefix. The session key is the addressing scheme for cross-bot relay messages.","triggerScenarios":"Calling Send (or the handleRelaySend command) with a SessionKey that is empty, has the wrong separator/format, or missing the platform or chatID component.","commonSituations":"Storing session keys from an older format after an upgrade; hand-crafting a key in scripts/tests instead of taking one from an established session; a platform adapter producing keys in a non-canonical format.","solutions":["Print/log the offending SessionKey and compare it with keys produced by the engine (e.g. from /sessions) to spot the format mismatch","Use a session key obtained from the platform/session APIs rather than constructing one manually","Inspect parseSessionKeyParts to confirm the expected format (separator and required parts) and fix the producer of the key"],"exampleFix":"// before\nreq := RelayRequest{SessionKey: chatID, From: \"feishu\", To: \"telegram\"}\n// after\nreq := RelayRequest{SessionKey: platform + \":\" + chatID, From: \"feishu\", To: \"telegram\"}","handlingStrategy":"validation","validationCode":"if req.SessionKey == \"\" || !strings.Contains(req.SessionKey, \":\") {\n    return fmt.Errorf(\"session key must be <platform>:<chatID>\")\n}","typeGuard":"func validSessionKey(k string) bool {\n    parts := strings.SplitN(k, \":\", 2)\n    return len(parts) == 2 && parts[0] != \"\" && parts[1] != \"\"\n}","tryCatchPattern":"resp, err := rm.Send(ctx, req)\nif err != nil {\n    var pe *parseError // or inspect the wrapped cause\n    if strings.Contains(err.Error(), \"invalid session key\") {\n        return nil, fmt.Errorf(\"re-share the session to get a fresh key: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Always source session keys from engine-generated sessions, never hand-build them","Add a round-trip test: format then parse a key for each platform","When upgrading versions, re-establish relay bindings rather than reusing stored keys"],"tags":["go","relay","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}