{"record":{"id":"3670d84004ef4a1b","repo":"chenhg5/cc-connect","slug":"dingtalk-invalid-session-key-format-q","errorCode":null,"errorMessage":"dingtalk: invalid session key format: %q","messagePattern":"dingtalk: invalid session key format: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1614,"sourceCode":"\tif len(runes) <= maxQuotedMessageRunes {\n\t\treturn text\n\t}\n\treturn string(runes[:maxQuotedMessageRunes]) + \"...\"\n}\n\n// ReconstructReplyCtx implements core.ReplyContextReconstructor.\n// Session key format: \"dingtalk:{convType}:{conversationId}:{senderStaffId}\" or \"dingtalk:{convType}:{conversationId}\"\n// where convType is \"g\" (group) or \"d\" (direct/1:1).\nfunc (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {\n\tif !strings.HasPrefix(sessionKey, \"dingtalk:\") {\n\t\treturn nil, fmt.Errorf(\"dingtalk: not a dingtalk session key: %q\", sessionKey)\n\t}\n\n\tstripped := strings.TrimPrefix(sessionKey, \"dingtalk:\")\n\tparts := strings.SplitN(stripped, \":\", 3)\n\n\tif len(parts) < 2 {\n\t\treturn nil, fmt.Errorf(\"dingtalk: invalid session key format: %q\", sessionKey)\n\t}\n\n\tconvType := parts[0]\n\tif convType != \"g\" && convType != \"d\" {\n\t\treturn nil, fmt.Errorf(\"dingtalk: invalid conversation type %q in session key: %q\", convType, sessionKey)\n\t}\n\n\tconversationId := parts[1]\n\tif conversationId == \"\" {\n\t\treturn nil, fmt.Errorf(\"dingtalk: empty conversationId in session key: %q\", sessionKey)\n\t}\n\n\tvar senderStaffId string\n\tif len(parts) > 2 {\n\t\tsenderStaffId = parts[2]\n\t}\n\n\treturn replyContext{","sourceCodeStart":1596,"sourceCodeEnd":1632,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1596-L1632","documentation":"The session key had the 'dingtalk:' prefix but, after stripping it, contained fewer than 2 colon-separated segments. The expected format is 'dingtalk:{convType}:{conversationId}' optionally followed by ':{senderStaffId}' — at minimum convType and conversationId must be present. The key is therefore structurally malformed.","triggerScenarios":"Passing 'dingtalk:' or 'dingtalk:g' (only one segment) to ReconstructReplyCtx; a key truncated by storage/export tooling; a hand-edited key missing the conversation id.","commonSituations":"Databases or config files where colons were mangled by escaping/interpolation; copying a partial key from logs; keys built against an older format before the convType segment was introduced.","solutions":["Print the offending key from the error and compare against 'dingtalk:{g|d}:{conversationId}[:{senderStaffId}]'.","Rebuild the key from a live incoming DingTalk message instead of hand-editing the stored value.","If keys were stored before a format change, migrate them to the current 3-4 segment format.","Ensure no tooling strips or splits on ':' when persisting the key (e.g. TOML/env escaping issues)."],"exampleFix":"// before\nsessionKey := \"dingtalk:g\"\nrc, err := platform.ReconstructReplyCtx(sessionKey) // error: invalid format\n// after\nsessionKey := \"dingtalk:g:cidXXXX\" // convType + conversationId\nrc, err := platform.ReconstructReplyCtx(sessionKey)","handlingStrategy":"validation","validationCode":"func validDingtalkKeyShape(key string) bool {\n    if !strings.HasPrefix(key, \"dingtalk:\") {\n        return false\n    }\n    rest := strings.TrimPrefix(key, \"dingtalk:\")\n    parts := strings.SplitN(rest, \":\", 3)\n    return len(parts) >= 2 && parts[0] != \"\" && parts[1] != \"\"\n}\n// call only if validDingtalkKeyShape(key) is true","typeGuard":"func hasMinSegments(key string) bool {\n    return len(strings.SplitN(strings.TrimPrefix(key, \"dingtalk:\"), \":\", 3)) >= 2\n}","tryCatchPattern":"ctx, err := platform.ReconstructReplyCtx(sessionKey)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid session key format\") {\n        slog.Error(\"malformed dingtalk key; refetch from sessions list\", \"key\", sessionKey)\n        return errKeyMalformed\n    }\n    return err\n}","preventionTips":["Always persist the full key including convType and conversationId segments.","Avoid tooling that splits/strips on ':' when storing keys (escape or encode if needed).","Regenerate keys from live messages after any adapter format change.","Add a shape-check helper before invoking reconstruction in scripts."],"tags":["session-key","parsing","validation","dingtalk"],"backgroundTag":"invalid-identifier-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"}