chenhg5/cc-connect · error

invalid session key format: %q

Error message

invalid session key format: %q

What it means

parseSessionKeyParts (core/relay.go:345) throws this when the session key splits into fewer than 2 colon-separated parts. Valid formats are 'platform:chatID:userID' or 'relay:sourceProject:chatID'; a bare string with no ':' cannot identify a platform/chat.

Source

Thrown at core/relay.go:345

	return fmt.Sprintf("[%s] %s", toName, truncateRelay(response, 2000))
}

func (rm *RelayManager) relayContext(ctx context.Context) (context.Context, context.CancelFunc) {
	rm.mu.RLock()
	timeout := rm.timeout
	rm.mu.RUnlock()
	if timeout <= 0 {
		return ctx, func() {}
	}
	return context.WithTimeout(ctx, timeout)
}

func parseSessionKeyParts(sessionKey string) (platform, chatID string, err error) {
	// Format: "platform:chatID:userID"
	// Relay session format: "relay:sourceProject:chatID"
	parts := strings.SplitN(sessionKey, ":", 3)
	if len(parts) < 2 {
		return "", "", fmt.Errorf("invalid session key format: %q", sessionKey)
	}
	if parts[0] == "relay" && len(parts) == 3 {
		// For relay sessions, chatID is the third part: "relay:sourceProject:chatID"
		return parts[0], parts[2], nil
	}
	return parts[0], parts[1], nil
}

// resolveGroupVisibilityKey computes the session key used for relay
// visibility echoes.  It defaults to "<platform>:<chatID>:relay" and
// gives the caller's platform a chance to override via the optional
// core.RelayGroupVisibilityTarget interface.
//
// Looking the platform up via sourceEngine.platforms (not targetEngine)
// matches the existing sendToGroup() resolution path — the visibility
// echo is dispatched as the source bot, so the source engine's
// platform impl is authoritative for the key format.
func (rm *RelayManager) resolveGroupVisibilityKey(platform, chatID, callerSessionKey string, sourceEngine *Engine) string {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Format the key as 'platform:chatID:userID' (e.g. 'feishu:oc_abc:ou_123') before passing it
  2. For relay-originated sessions use 'relay:sourceProject:chatID'
  3. Validate the key contains at least one ':' before calling Send/cmdBind
  4. Use the engine's real session key (from the incoming message context) instead of a hand-built one

Example fix

// before
rm.Send(ctx, core.RelayRequest{SessionKey: "oc_abc123", ...})
// after
rm.Send(ctx, core.RelayRequest{SessionKey: "feishu:oc_abc123:ou_456", ...})
Defensive patterns

Strategy: validation

Validate before calling

func validSessionKey(k string) bool {
	return len(strings.SplitN(k, ":", 3)) >= 2
}
if !validSessionKey(req.SessionKey) { return errors.New("session key must be platform:chatID[:userID] or relay:sourceProject:chatID") }

Type guard

func asSessionKey(parts ...string) (string, bool) {
	if len(parts) < 2 { return "", false }
	for _, p := range parts { if p == "" { return "", false } }
	return strings.Join(parts, ":"), true
}

Try / catch

resp, err := rm.Send(ctx, req)
if err != nil {
	if strings.Contains(err.Error(), "invalid session key") || strings.Contains(err.Error(), "invalid session key format") {
		reply("Internal error: malformed session key "+req.SessionKey)
		return
	}
	return err
}

Prevention

When it happens

Trigger: Passing an empty string, a bare chatID like 'oc_abc123', a session key built without the platform prefix, or a malformed key such as 'feishu' to parseSessionKeyParts via Send, cmdBind, or relayContextForSourceSessionKey.

Common situations: Constructing session keys manually in tests or scripts and forgetting the platform prefix; storing only the chatID in a database and passing it as the full key; empty SessionKey field in a RelayRequest or /bind command payload.

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


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