xpzouying/xiaohongshu-mcp · error

unmarshal current user failed

Error message

unmarshal current user failed

What it means

CurrentUser builds a JSON string inside the page (JSON.stringify of nickname/userId) and decodes it into the CurrentUser struct with json.Unmarshal. 'unmarshal current user failed' means the string returned by the page is not valid JSON or its shape doesn't satisfy the struct's expectations, so decoding into CurrentUser{Nickname,UserID} failed.

Source

Thrown at xiaohongshu/login.go:67

	res, err := pp.Eval(`() => {
		const u = window.__INITIAL_STATE__ && window.__INITIAL_STATE__.user;
		const info = u && u.userInfo && u.userInfo.value !== undefined ? u.userInfo.value : (u && u.userInfo);
		if (!info || info.guest) return "";
		return JSON.stringify({nickname: info.nickname, userId: info.userId || info.user_id});
	}`)
	if err != nil {
		return nil, errors.Wrap(err, "read current user state failed")
	}

	raw := res.Value.String()
	if raw == "" {
		return nil, errors.New("current user not found in page state")
	}

	var user CurrentUser
	if err := json.Unmarshal([]byte(raw), &user); err != nil {
		return nil, errors.Wrap(err, "unmarshal current user failed")
	}

	return &user, nil
}

func (a *LoginAction) Login(ctx context.Context) error {
	pp := a.page.Context(ctx)

	// 导航到小红书首页,这会触发二维码弹窗
	pp.MustNavigate("https://www.xiaohongshu.com/explore").MustWaitLoad()

	time.Sleep(2 * time.Second)

	if exists, _, _ := pp.Has(".main-container .user .link-wrapper .channel"); exists {
		return nil
	}

	pp.MustElement(".main-container .user .link-wrapper .channel")

View on GitHub (pinned to 332d196854)

Solutions

  1. Log the raw value of res.Value.String() to see what the page actually returned
  2. Compare it against the CurrentUser struct {nickname string, userId string} and update the eval JS or struct tags to match the new site shape
  3. Make the eval stricter: build the object explicitly with String(info.nickname) and String(info.userId||info.user_id) so Unmarshal always receives strings
  4. Pin/update the library version after checking whether xiaohongshu changed __INITIAL_STATE__ (this is a scraping-fragility error, not a caller bug)

Example fix

// before
return JSON.stringify({nickname: info.nickname, userId: info.userId || info.user_id});
// after
return JSON.stringify({nickname: String(info.nickname ?? ""), userId: String(info.userId ?? info.user_id ?? "")});
Defensive patterns

Strategy: type-guard

Validate before calling

raw := ""
// decode defensively after reading page state
var probe map[string]any
if err := json.Unmarshal([]byte(raw), &probe); err != nil { return nil, fmt.Errorf("page returned non-JSON: %q", raw) }

Type guard

func looksLikeUserJSON(s string) bool {
    var v struct {
        Nickname string `json:"nickname"`
        UserID   string `json:"userId"`
    }
    return json.Unmarshal([]byte(s), &v) == nil
}

Try / catch

user, err := login.CurrentUser(ctx)
if err != nil {
    if strings.Contains(err.Error(), "unmarshal current user failed") {
        // site state shape changed; log raw payload and degrade gracefully
        return nil, ErrUserParseUnavailable
    }
    return err
}

Prevention

When it happens

Trigger: The page's __INITIAL_STATE__ yields fields that are not strings (e.g. userId as a number is fine, but nested objects/arrays serialized differently will not match); a xiaohongshu front-end change makes the eval return a different structure (e.g. the whole info object instead of {nickname,userId}); locale/encoding issues corrupt the JSON string.

Common situations: Site redesign moving user info out of __INITIAL_STATE__.user.userInfo; the eval's fallback branch (u.userInfo without .value) returning an object with extra/non-JSON-compatible content; data races where the state updates mid-stringify.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05). Data as JSON: /api/errors/47d79e277e77becb. Report an issue: GitHub.