{"record":{"id":"abad3064abece27e","repo":"xpzouying/xiaohongshu-mcp","slug":"failed-to-unmarshal-userpagedata-w","errorCode":null,"errorMessage":"failed to unmarshal userPageData: %w","messagePattern":"failed to unmarshal userPageData: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/user_profile.go","lineNumber":105,"sourceCode":"\t\tif (!u || !u.notes) return \"\";\n\t\tconst unwrap = (o) => (o && o.value !== undefined) ? o.value : (o && o._value);\n\t\tconst notes = unwrap(u.notes);\n\t\tif (!notes) return \"\";\n\t\tconst active = unwrap(u.activeTab) || {};\n\t\treturn JSON.stringify({notes: notes, index: active.index || 0, query: active.query || \"\"});\n\t}`).String()\n\n\tif notesResult == \"\" {\n\t\treturn nil, fmt.Errorf(\"user.notes.value not found in __INITIAL_STATE__\")\n\t}\n\n\t// 解析用户信息\n\tvar userPageData struct {\n\t\tInteractions []UserInteractions `json:\"interactions\"`\n\t\tBasicInfo    UserBasicInfo      `json:\"basicInfo\"`\n\t}\n\tif err := json.Unmarshal([]byte(userDataResult), &userPageData); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal userPageData: %w\", err)\n\t}\n\n\tvar notesData struct {\n\t\tNotes [][]Feed `json:\"notes\"`\n\t\tIndex int      `json:\"index\"`\n\t\tQuery string   `json:\"query\"`\n\t}\n\tif err := json.Unmarshal([]byte(notesResult), &notesData); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal notes: %w\", err)\n\t}\n\n\t// tab 不符时报错，避免把别的 tab 的内容当成结果返回\n\twant := tab\n\tif want == \"\" {\n\t\twant = TabNotes\n\t}\n\tif notesData.Query != \"\" && ProfileTab(notesData.Query) != want {\n\t\treturn nil, fmt.Errorf(\"当前 tab 为 %q，与请求的 %q 不符\", notesData.Query, want)","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/user_profile.go#L87-L123","documentation":"extractUserProfileData 已拿到 userPageData JSON，但 json.Unmarshal 到匿名结构体（interactions/basicInfo）失败：页面数据结构与定义不符（前端改版）或数据截断。","triggerScenarios":"调用 UserProfile / GetMyProfileViaSidebar 时，__INITIAL_STATE__ 中 userPageData.value 的 JSON 字段类型/结构与 UserInteractions、UserBasicInfo 定义不符，导致 Unmarshal 报错（如类型变化、字符串变数字、null 处理）。","commonSituations":"小红书改版调整了 basicInfo/interactions 字段类型；新增/删除字段导致结构不兼容；Eval 返回的是 \"null\" 字符串而非合法 JSON 对象。","solutions":["查看包装的底层 json 错误定位具体字段，升级库版本适配新 schema","检查返回的 userDataResult 是否为 null/空对象（数据缺失被序列化成了 JSON）","必要时在本地用自定义解析兼容新字段","向库维护者报告新版页面结构差异"],"exampleFix":"// before\nres, err := client.UserProfile(ctx, userID, \"note\") // Unmarshal 失败\n// after\nif err != nil && strings.Contains(err.Error(), \"unmarshal userPageData\") {\n    log.Printf(\"页面 schema 可能已变更: %v\", err) // 查看底层 %w 错误\n    return upgradeLibraryAndRetry()\n}","handlingStrategy":"type-guard","validationCode":"// 调用前检查返回的 JSON 非空且非 null\nif userDataResult == \"\" || userDataResult == \"null\" {\n    return errors.New(\"userPageData 为空，页面可能未加载完成\")\n}","typeGuard":"func looksLikeUserPageData(raw string) bool {\n    var probe struct {\n        BasicInfo json.RawMessage `json:\"basicInfo\"`\n    }\n    return json.Unmarshal([]byte(raw), &probe) == nil && len(probe.BasicInfo) > 0\n}","tryCatchPattern":"res, err := client.UserProfile(ctx, userID, tab)\nvar jsonErr error\nif err != nil && errors.As(err, &jsonErr) && strings.Contains(err.Error(), \"unmarshal userPageData\") {\n    // 底层 %w 错误可定位具体字段，提示 schema 变更\n    log.Printf(\"schema 变更: %v\", jsonErr)\n}","preventionTips":["错误经 %w 包装，用 errors.As/Is 解包定位具体字段","跟进小红书 state schema 变更并及时升级库","对 null/缺失字段在结构体中使用指针或 json.RawMessage","保留底层错误日志便于上报维护者"],"tags":["json","unmarshal","schema","scraping"],"backgroundTag":"json-unmarshal-failed","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"}