{"record":{"id":"4e877a8a2fb3529e","repo":"chenhg5/cc-connect","slug":"max-cannot-reconstruct-reply-ctx-from-q","errorCode":null,"errorMessage":"max: cannot reconstruct reply ctx from %q","messagePattern":"max: cannot reconstruct reply ctx from %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/max/max.go","lineNumber":741,"sourceCode":"// MAX-supported markdown syntax.\nfunc (p *Platform) FormattingInstructions() string {\n\treturn `Formatting rules for MAX messenger:\n- **bold** and _italic_ are supported\n- Inline code: ` + \"`code`\" + ` and fenced code blocks (` + \"```\" + `) are supported\n- Bullet lists with - or * are supported as plain text\n- Do NOT use headers (# ## ###)\n- Do NOT use horizontal rules (--- or ***)\n- Do NOT use tables\n- Do NOT use HTML tags\nKeep responses concise and use plain text where possible.`\n}\n\n// ReconstructReplyCtx implements core.ReplyContextReconstructor.\n// Session key format: \"max:{chatID}\" or \"max:{chatID}:{userID}\".\nfunc (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {\n\trest, ok := strings.CutPrefix(sessionKey, \"max:\")\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"max: cannot reconstruct reply ctx from %q\", sessionKey)\n\t}\n\tchatID, _, _ := strings.Cut(rest, \":\")\n\tif chatID == \"\" {\n\t\treturn nil, fmt.Errorf(\"max: cannot reconstruct reply ctx from %q\", sessionKey)\n\t}\n\treturn replyContext{chatID: chatID}, nil\n}\n\n// --- MAX API types ---\n\ntype maxButton struct {\n\tType    string `json:\"type\"`\n\tText    string `json:\"text\"`\n\tPayload string `json:\"payload\"`\n}\n\n// maxOutAttachment is the generic outgoing attachment wrapper used for both\n// inline_keyboard (with maxKbPayload) and image/file/video/audio (with","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/max/max.go#L723-L759","documentation":"ReconstructReplyCtx rebuilds a replyContext from a session key of the form \"max:{chatID}\" or \"max:{chatID}:{userID}\" so the engine can reply to a restored session. If the key does not carry the required \"max:\" prefix, the platform cannot recognize it as a MAX session and returns this error. It guards against feeding keys produced by other platforms into the MAX reconstructor.","triggerScenarios":"Calling ReconstructReplyCtx with a session key like \"feishu:oc_123\" or a bare chat id \"12345\" (no \"max:\" prefix), typically from a session store mixing multiple platform keys, or after a config change that renamed the platform.","commonSituations":"Cross-platform session stores where keys from Telegram/Feishu are passed to the MAX platform; hand-crafted keys in tests or tooling missing the prefix; a platform name change leaving legacy keys without \"max:\".","solutions":["Pass only session keys that begin with \"max:\"; filter or route keys to the correct platform's reconstructor first.","Inspect the offending key in the error message (%q) to identify which platform produced it and use that platform's ReconstructReplyCtx.","If keys predate a rename, migrate stored keys to the current \"max:{chatID}\" format.","Normalize the key: if it is a bare numeric chat id, wrap it as \"max:\"+chatID before calling."],"exampleFix":"// before (any key goes to max)\nctx, err := maxPlatform.ReconstructReplyCtx(sessionKey)\n// after: dispatch by prefix\nvar ctx any\nswitch {\ncase strings.HasPrefix(sessionKey, \"max:\"):\n\tctx, err = maxPlatform.ReconstructReplyCtx(sessionKey)\ncase strings.HasPrefix(sessionKey, \"feishu:\"):\n\tctx, err = feishuPlatform.ReconstructReplyCtx(sessionKey)\ndefault:\n\terr = fmt.Errorf(\"unknown session key format: %q\", sessionKey)\n}","handlingStrategy":"type-guard","validationCode":"// Route by prefix before calling the MAX reconstructor\nfunc isMaxSessionKey(key string) bool { return strings.HasPrefix(key, \"max:\") }\nif !isMaxSessionKey(sessionKey) {\n\treturn fmt.Errorf(\"not a max session key: %q\", sessionKey)\n}","typeGuard":"func isMaxKey(s string) bool {\n\trest, ok := strings.CutPrefix(s, \"max:\")\n\tif !ok { return false }\n\tchatID, _, _ := strings.Cut(rest, \":\")\n\treturn chatID != \"\"\n}","tryCatchPattern":"ctx, err := p.ReconstructReplyCtx(sessionKey)\nif err != nil {\n\tslog.Warn(\"max: cannot restore session\", \"key\", sessionKey, \"err\", err)\n\t// fall back to starting a fresh session for this chat\n\treturn startNewSession(chatID)\n}","preventionTips":["Namespace all session keys with the platform prefix and enforce it at write time.","Keep a registry mapping platform prefix → ReconstructReplyCtx so keys are dispatched correctly.","Migrate legacy unprefixed keys after any platform rename.","Test key round-tripping (format → reconstruct) for every platform in CI."],"tags":["session","parsing","max"],"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"}