{"record":{"id":"1ca577fba0681dd9","repo":"chenhg5/cc-connect","slug":"slack-invalid-session-key-q","errorCode":null,"errorMessage":"slack: invalid session key %q","messagePattern":"slack: invalid session key %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/slack/slack.go","lineNumber":597,"sourceCode":"\n\tdata, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read response body: %w\", err)\n\t}\n\n\t// Basic sanity check: detect if we received HTML instead of binary data\n\tif len(data) > 0 && (bytes.HasPrefix(data, []byte(\"<!DOCTYPE\")) || bytes.HasPrefix(data, []byte(\"<html\"))) {\n\t\treturn nil, fmt.Errorf(\"received HTML response (likely missing auth); first 100 bytes: %s\", string(data[:min(100, len(data))]))\n\t}\n\n\treturn data, nil\n}\n\nfunc (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {\n\t// slack:{channel}:{user}  |  slack:{channel}:t:{threadTS}  |  slack:{channel}\n\tparts := strings.SplitN(sessionKey, \":\", 3)\n\tif len(parts) < 2 || parts[0] != \"slack\" {\n\t\treturn nil, fmt.Errorf(\"slack: invalid session key %q\", sessionKey)\n\t}\n\trc := replyContext{channel: parts[1]}\n\t// Thread-scoped keys carry the thread root ts as a \"t:<ts>\" suffix; preserve\n\t// it so proactive replies (cron, send-to-session, restart/model/delete\n\t// notifications) post into the original thread instead of the channel root.\n\tif len(parts) == 3 && strings.HasPrefix(parts[2], \"t:\") {\n\t\trc.timestamp = strings.TrimPrefix(parts[2], \"t:\")\n\t}\n\treturn rc, nil\n}\n\nfunc (p *Platform) resolveUserName(userID string) string {\n\tif cached, ok := p.userNameCache.Load(userID); ok {\n\t\treturn cached.(string)\n\t}\n\tuser, err := p.client.GetUserInfo(userID)\n\tif err != nil {\n\t\tslog.Debug(\"slack: resolve user name failed\", \"user\", userID, \"error\", err)","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/slack/slack.go#L579-L615","documentation":"ReconstructReplyCtx rebuilds a replyContext from a persisted session key string. The key must be 'slack:{channel}', 'slack:{channel}:{user}', or 'slack:{channel}:t:{threadTS}'. This error is thrown when the string has fewer than two colon-separated parts or does not start with the 'slack' prefix — i.e. the stored key is malformed or belongs to another platform.","triggerScenarios":"Calling ReconstructReplyCtx with a session key written by a different platform adapter (e.g. 'telegram:123'), an empty string, a truncated key, or a legacy key format saved before the thread 't:' scheme existed.","commonSituations":"Restoring sessions from an old config/db after switching platforms; hand-editing session keys; a bug in whatever persisted the key; passing a channel name instead of the full key.","solutions":["Print/log the offending key and confirm it matches 'slack:{channel}[:{user}|:t:{threadTS}]'","Delete or re-create the stale session so the engine regenerates a correctly formatted key","Check that the session key was produced by the slack adapter, not another platform","If migrating formats, migrate stored keys to the current scheme before restart"],"exampleFix":"// before\ncfg.SessionKey = \"1234567890\" // missing platform prefix\nrc, err := p.ReconstructReplyCtx(cfg.SessionKey)\n// after\ncfg.SessionKey = \"slack:C0123456789\"\nrc, err := p.ReconstructReplyCtx(cfg.SessionKey)","handlingStrategy":"validation","validationCode":"func validSlackKey(k string) bool {\n    p := strings.SplitN(k, \":\", 3)\n    return len(p) >= 2 && p[0] == \"slack\" && p[1] != \"\"\n}\nif !validSlackKey(sessionKey) { return errors.New(\"malformed slack session key\") }","typeGuard":null,"tryCatchPattern":"rc, err := p.ReconstructReplyCtx(sessionKey)\nif err != nil {\n    slog.Warn(\"dropping session with bad key\", \"key\", sessionKey, \"err\", err)\n    return nil // recreate session instead of failing the flow\n}","preventionTips":["Only pass keys produced by the slack adapter (prefix 'slack:')","Never hand-edit stored session keys","Migrate legacy key formats before restart","Log and skip malformed keys instead of crashing the restore path"],"tags":["slack","session-key","parsing","format"],"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"}