{"record":{"id":"91f418899a22b1db","repo":"chenhg5/cc-connect","slug":"discord-invalid-session-key-q","errorCode":null,"errorMessage":"discord: invalid session key %q","messagePattern":"discord: invalid session key %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/discord/discord.go","lineNumber":327,"sourceCode":"\t}\n\treturn truncateDiscordThreadName(name, 90)\n}\n\nfunc standaloneThreadType(parentType discordgo.ChannelType) (discordgo.ChannelType, bool) {\n\tswitch parentType {\n\tcase discordgo.ChannelTypeGuildText:\n\t\treturn discordgo.ChannelTypeGuildPublicThread, true\n\tcase discordgo.ChannelTypeGuildNews:\n\t\treturn discordgo.ChannelTypeGuildNewsThread, true\n\tdefault:\n\t\treturn 0, false\n\t}\n}\n\nfunc parseDiscordSessionKeyChannelID(sessionKey string) (string, error) {\n\tparts := strings.SplitN(sessionKey, \":\", 3)\n\tif len(parts) < 2 || parts[0] != \"discord\" || parts[1] == \"\" {\n\t\treturn \"\", fmt.Errorf(\"discord: invalid session key %q\", sessionKey)\n\t}\n\treturn parts[1], nil\n}\n\nfunc resolveSessionKeyForChannel(channelID, userID string, shareSessionInChannel bool, threadIsolation bool, ops discordThreadOps) string {\n\tif !threadIsolation {\n\t\treturn buildSessionKey(channelID, userID, shareSessionInChannel)\n\t}\n\tch, err := ops.ResolveChannel(channelID)\n\tif err != nil {\n\t\tslog.Warn(\"discord: resolve channel for session key failed, falling back\", \"channel\", channelID, \"error\", err)\n\t\treturn buildSessionKey(channelID, userID, shareSessionInChannel)\n\t}\n\tif isThreadChannelType(ch.Type) {\n\t\treturn buildThreadSessionKey(channelID)\n\t}\n\treturn buildSessionKey(channelID, userID, shareSessionInChannel)\n}","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/discord/discord.go#L309-L345","documentation":"Session keys in this codebase are namespaced strings of the form \"discord:<channelID>[:threadID]\". parseDiscordSessionKeyChannelID rejects any key whose first segment is not \"discord\" or whose channel segment is empty. resolveCronReplyTarget hits this when handed a session key that does not belong to the Discord platform or is malformed.","triggerScenarios":"resolveCronReplyTarget receives a sessionKey from config or stored state that is empty, missing the \"discord:\" prefix, or has an empty channel ID — e.g. a cron job saved under a Telegram/Feishu session key or written by an older format.","commonSituations":"Cron job config pointing at the wrong platform's session, hand-edited config.toml session keys, stale persisted session keys from a pre-thread-isolation format, or copy-pasted keys across platform configs.","solutions":["Fix the cron job's sessionKey so it is \"discord:<channelID>\" with a non-empty channel ID.","Validate session keys at config-load time before scheduling the cron job.","If the key came from persisted state, re-create the cron job from a live Discord session so the key is regenerated correctly.","Check that the cron target belongs to this Discord platform instance, not another platform's agent session."],"exampleFix":"// before\n[agent.cron]\nsessionKey = \"feishu:ou_123\"   # wrong platform\n// after\n[agent.cron]\nsessionKey = \"discord:123456789012345678\"","handlingStrategy":"validation","validationCode":"func validDiscordSessionKey(k string) bool {\n    parts := strings.SplitN(k, \":\", 3)\n    return len(parts) >= 2 && parts[0] == \"discord\" && parts[1] != \"\"\n}\n// before scheduling: if !validDiscordSessionKey(cfg.SessionKey) { reject }","typeGuard":null,"tryCatchPattern":"chID, err := parseDiscordSessionKeyChannelKey(key)\nif err != nil {\n    return fmt.Errorf(\"cron target is not a Discord session key: %w\", err)\n}","preventionTips":["Validate session keys when the cron job is created, not at fire time.","Never hand-edit session keys; generate them from a live session.","Migrate/validate persisted keys after upgrading formats."],"tags":["discord","session-key","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"}