{"record":{"id":"4b4537d364156613","repo":"xpzouying/xiaohongshu-mcp","slug":"failed-to-unmarshal-notedetailmap-w","errorCode":null,"errorMessage":"failed to unmarshal noteDetailMap: %w","messagePattern":"failed to unmarshal noteDetailMap: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/feed_detail.go","lineNumber":989,"sourceCode":"\t\t}),\n\t)\n\n\tif err != nil {\n\t\tlogrus.Errorf(\"提取Feed详情失败: %v\", err)\n\t\treturn nil, fmt.Errorf(\"提取Feed详情失败: %w\", err)\n\t}\n\n\tif result == \"\" {\n\t\treturn nil, errors.ErrNoFeedDetail\n\t}\n\n\tvar noteDetailMap map[string]struct {\n\t\tNote     FeedDetail  `json:\"note\"`\n\t\tComments CommentList `json:\"comments\"`\n\t}\n\n\tif err := json.Unmarshal([]byte(result), &noteDetailMap); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal noteDetailMap: %w\", err)\n\t}\n\n\tnoteDetail, exists := noteDetailMap[feedID]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"feed %s not found in noteDetailMap\", feedID)\n\t}\n\n\treturn &FeedDetailResponse{\n\t\tNote:     noteDetail.Note,\n\t\tComments: noteDetail.Comments,\n\t}, nil\n}\n\nfunc makeFeedDetailURL(feedID, xsecToken string) string {\n\treturn fmt.Sprintf(\"https://www.xiaohongshu.com/explore/%s?xsec_token=%s&xsec_source=pc_feed\", feedID, xsecToken)\n}\n","sourceCodeStart":971,"sourceCodeEnd":1006,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/feed_detail.go#L971-L1006","documentation":"After extraction, extractFeedDetail unmarshals the JSON string into a map keyed by feed ID with note/comments payloads. If the JSON doesn't match that shape, it throws 'failed to unmarshal noteDetailMap: %w'.","triggerScenarios":"The __INITIAL_STATE__ JSON schema changed (fields renamed, note data nested differently) or the extracted string is truncated/HTML rather than the expected map.","commonSituations":"xiaohongshu frontend update altering the noteDetailMap structure; extraction snippet grabbing the wrong object; empty/partial page state serialized with unexpected types.","solutions":["Log the raw result string and compare against the expected schema","Update the FeedDetail/CommentList struct json tags to match the current API shape","Validate the JSON (jq or a quick unmarshal to map[string]any) to find where it diverges"],"exampleFix":"// before\nvar noteDetailMap map[string]struct{ Note FeedDetail `json:\"note\"`; Comments CommentList `json:\"comments\"` }\n// after — inspect first\nvar raw map[string]json.RawMessage\nif err := json.Unmarshal([]byte(result), &raw); err != nil { log.Printf(\"raw=%s\", result); return nil, err }","handlingStrategy":"type-guard","validationCode":"func looksLikeDetailMap(raw string) bool {\n    var probe map[string]json.RawMessage\n    return json.Unmarshal([]byte(raw), &probe) == nil && len(probe) > 0\n}","typeGuard":"func asNoteDetailMap(raw string) (map[string]json.RawMessage, bool) {\n    var m map[string]json.RawMessage\n    if err := json.Unmarshal([]byte(raw), &m); err != nil || m == nil { return nil, false }\n    return m, true\n}","tryCatchPattern":"detail, err := client.GetFeedDetailWithConfig(ctx, id, cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"unmarshal noteDetailMap\") {\n        log.Errorf(\"schema drift on %s: %v\", id, err); return err\n    }\n    return err\n}","preventionTips":["Pin/monitor library version against xiaohongshu frontend changes","Log raw extraction payloads on failure for schema debugging","Add a canary test that fetches one known-good note daily"],"tags":["json","unmarshal","schema-mismatch"],"backgroundTag":"json-unmarshal-error","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}