{"record":{"id":"139f240a357c44f7","repo":"xpzouying/xiaohongshu-mcp","slug":"failed-to-unmarshal-notes-w","errorCode":null,"errorMessage":"failed to unmarshal notes: %w","messagePattern":"failed to unmarshal notes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/user_profile.go","lineNumber":114,"sourceCode":"\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)\n\t}\n\n\t// 组装响应\n\tresponse := &UserProfileResponse{\n\t\tUserBasicInfo: userPageData.BasicInfo,\n\t\tInteractions:  userPageData.Interactions,\n\t}\n\n\t// 每个 tab 的内容存在各自的下标里，只取当前 tab 的，避免混入其他 tab","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/user_profile.go#L96-L132","documentation":"extractUserProfileData 已拿到 notes JSON，但 json.Unmarshal 到 notesData（notes 二维数组/index/query）失败：笔记数据结构与结构体定义不匹配或 JSON 非法。","triggerScenarios":"调用 UserProfile / GetMyProfileViaSidebar 时，__INITIAL_STATE__.user.notes.value 的 JSON 结构与 [][]Feed 不符——例如 Feed 内字段类型变化（id 从数字变字符串）、notes 变为一维数组、包含 null 项。","commonSituations":"小红书改版调整了 Feed 结构；笔记列表含特殊卡片（广告/置顶）字段类型不同；activeTab 序列化后出现 null 嵌套导致数组元素非法。","solutions":["按底层 %w 错误定位不兼容字段，升级库版本适配新 Feed 结构","检查 notesResult 是否含 null 元素或一维结构","若仅个别笔记触发，可尝试缩小返回范围或过滤后再解析","向维护者报告结构差异"],"exampleFix":"// before\nres, err := client.UserProfile(ctx, userID, \"note\")\n// after\nif err != nil && strings.Contains(err.Error(), \"unmarshal notes\") {\n    log.Printf(\"Feed schema 可能已变更: %v\", err)\n    return handleSchemaChange(err)\n}","handlingStrategy":"type-guard","validationCode":"if notesResult == \"\" || notesResult == \"null\" {\n    return errors.New(\"notes 数据为空\")\n}","typeGuard":"func looksLikeNotes(raw string) bool {\n    var probe struct {\n        Notes [][]json.RawMessage `json:\"notes\"`\n    }\n    return json.Unmarshal([]byte(raw), &probe) == nil && len(probe.Notes) > 0\n}","tryCatchPattern":"res, err := client.UserProfile(ctx, userID, tab)\nif err != nil && strings.Contains(err.Error(), \"unmarshal notes\") {\n    var base error\n    errors.As(err, &base) // 取底层 json 错误定位不兼容字段\n    return handleFeedSchemaChange(err)\n}","preventionTips":["用 errors.As 解包 %w 定位具体不兼容字段","Feed 结构变更（字段类型/嵌套层级）时及时升级库","对可能为 null 的数组元素做防御（RawMessage 探测）","记录原始 notesResult 便于离线排查 schema 差异"],"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"}