chenhg5/cc-connect · error
relay: invalid session key: %w
Error message
relay: invalid session key: %w
What it means
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.
Source
Thrown at core/relay.go:208
// RelayRequest is the payload for a relay send.
type RelayRequest struct {
From string `json:"from"` // source project name
To string `json:"to"` // target project name
SessionKey string `json:"session_key"` // source session key (contains platform + chatID)
Message string `json:"message"`
}
// RelayResponse is the result of a relay send.
type RelayResponse struct {
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)
}View on GitHub (pinned to 4000b2338a)
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
Example fix
// before
req := RelayRequest{SessionKey: chatID, From: "feishu", To: "telegram"}
// after
req := RelayRequest{SessionKey: platform + ":" + chatID, From: "feishu", To: "telegram"} Defensive patterns
Strategy: validation
Validate before calling
if req.SessionKey == "" || !strings.Contains(req.SessionKey, ":") {
return fmt.Errorf("session key must be <platform>:<chatID>")
} Type guard
func validSessionKey(k string) bool {
parts := strings.SplitN(k, ":", 2)
return len(parts) == 2 && parts[0] != "" && parts[1] != ""
} Try / catch
resp, err := rm.Send(ctx, req)
if err != nil {
var pe *parseError // or inspect the wrapped cause
if strings.Contains(err.Error(), "invalid session key") {
return nil, fmt.Errorf("re-share the session to get a fresh key: %w", err)
}
return nil, err
} Prevention
- 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
When it happens
Trigger: Calling Send (or the handleRelaySend command) with a SessionKey that is empty, has the wrong separator/format, or missing the platform or chatID component.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid source session key: %w
- resolve relay workspace: %w
- agent error (no details)
- parse JSON from %s: %w
- cannot parse local reference
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/65cf77e62d49b82c.
Report an issue: GitHub.