Skip to content

feat(xhs): add AccountRestrictedError + upgrade 300011 raise sites (F001)#416

Merged
github-actions[bot] merged 5 commits intomainfrom
feature/xhs-account-restriction-detection
Apr 26, 2026
Merged

feat(xhs): add AccountRestrictedError + upgrade 300011 raise sites (F001)#416
github-actions[bot] merged 5 commits intomainfrom
feature/xhs-account-restriction-detection

Conversation

@0xmariowu
Copy link
Copy Markdown
Owner

Summary

  • Adds AccountRestrictedError(ChannelAuthError) typed exception for the XHS account-restriction case (code=300011)
  • Upgrades two existing raise ChannelAuthError(...) sites in via_signsrv.py to use the more precise type — fallback chain still works (subclass of ChannelAuthError), but downstream surfaces can distinguish "account flagged" from "missing/expired credentials"
  • Updates XHS SKILL.md § Known Issue to mark mitigation as implemented

Background

Plan: docs/exec-plans/active/autosearch-0426-xhs-account-restriction-detection.md — F001 path B.

The plan author originally believed the empty-results health probe was unimplemented; we discovered (via grep + Read) that via_signsrv.py:184-229 already had the inline mitigation, just raising the generic ChannelAuthError. Path B (advisor-confirmed) is the minimal-scope correction: keep S1's new precise type, upgrade the existing raise sites instead of extracting a helper just for testing's sake.

Behavior preservation

AccountRestrictedError is a subclass of ChannelAuthError. Reviewer (pr-review-toolkit:code-reviewer) verified all consumer paths:

  • _CompiledChannel.search fallback chain (channels/base.py:208-216) — except ChannelAuthError still matches; same recoverable-error handling
  • core/channel_status.py:49 — maps to status="auth_failed", reason field includes class name → host agent now sees AccountRestrictedError instead of generic ChannelAuthError
  • xueqiu/methods/api_search.py — short-circuit + priority-class logic both safe under subclass

Test plan

  • New tests: test_channels_base.py asserts AccountRestrictedErrorChannelAuthErrorPermanentError and message preservation
  • Updated test: test_xhs_signsrv_account_restriction.py asserts raised exception is AccountRestrictedError (not just base class)
  • New test in same file: test_xhs_signsrv_empty_search_with_me_300011_is_account_restricted_subclass — verifies actual instance is BOTH AccountRestrictedError AND ChannelAuthError (locks in subclass invariant)
  • Local fast suite: 649 passed, 0 regressions
  • Pre-push hook: 1076 passed
  • Code-reviewer: APPROVE

Subclass of ChannelAuthError so the existing fallback chain treats it
the same way (switch to next method), but the host agent surface gets a
more actionable message. Used by upcoming XHS account-restriction
detection (plan F001 S1).
Plan F001 S1 — covers (a) subclass relationship to ChannelAuthError +
PermanentError, (b) message preservation via str(exc).
…hError

Both 300011 raise sites in via_signsrv (the inline-300011 branch and
the empty-results probe branch) now raise the more precise
AccountRestrictedError type. AccountRestrictedError is a subclass of
ChannelAuthError so the existing fallback chain still treats it as a
recoverable auth failure (switches to via_tikhub) — but downstream
surfaces can now distinguish 'account flagged' from 'missing/expired
credentials'.

Plan F001 path B (advisor-confirmed minimal scope after discovering the
mitigation was already implemented inline).
- Existing test renamed + assertion upgraded to AccountRestrictedError.
- New test_xhs_signsrv_empty_search_with_me_300011_is_account_restricted_subclass
  proves the raised exception is BOTH AccountRestrictedError AND
  ChannelAuthError, so the fallback chain still recognizes it.
Mitigation block now describes the actual behavior: empty-results probe
+ AccountRestrictedError raise. AccountRestrictedError is a subclass of
ChannelAuthError so the fallback chain still recognizes it.
Copilot AI review requested due to automatic review settings April 26, 2026 03:47
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Warning

Rate limit exceeded

@0xmariowu has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 33 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 5 minutes and 33 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8d9ab6af-f68b-40ba-b9a5-968c42cdee25

📥 Commits

Reviewing files that changed from the base of the PR and between defb67c and 721adb8.

📒 Files selected for processing (5)
  • autosearch/channels/base.py
  • autosearch/skills/channels/xiaohongshu/SKILL.md
  • autosearch/skills/channels/xiaohongshu/methods/via_signsrv.py
  • tests/unit/test_channels_base.py
  • tests/unit/test_xhs_signsrv_account_restriction.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot enabled auto-merge (squash) April 26, 2026 03:48
@github-actions github-actions Bot merged commit a82fedc into main Apr 26, 2026
17 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a more specific typed auth failure for Xiaohongshu (XHS) account restriction (code=300011) so downstream surfaces can distinguish “account flagged” from generic authentication failures while preserving the existing fallback-chain behavior.

Changes:

  • Added AccountRestrictedError(ChannelAuthError) to represent upstream account-restriction/flagged states.
  • Updated XHS via_signsrv to raise AccountRestrictedError at the two code=300011 detection sites.
  • Updated XHS skill documentation and unit tests to reflect/validate the new exception type.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
autosearch/channels/base.py Adds the new AccountRestrictedError exception type as a ChannelAuthError subclass.
autosearch/skills/channels/xiaohongshu/methods/via_signsrv.py Switches code=300011 raises from ChannelAuthError to AccountRestrictedError.
autosearch/skills/channels/xiaohongshu/SKILL.md Updates the “Known Issue” mitigation notes to reflect the implemented detection + new exception type.
tests/unit/test_xhs_signsrv_account_restriction.py Updates the existing test to expect AccountRestrictedError and adds a subclass-invariant test.
tests/unit/test_channels_base.py Adds unit tests asserting subclass relationships and message preservation for AccountRestrictedError.

Comment on lines +53 to +57
"""Raised when a search returned no results because the account itself
is flagged/restricted upstream (e.g. XHS code=300011), distinct from a
generic ChannelAuthError (which means missing/expired credentials). The
fallback chain treats both the same -- switch to the next method -- but
the host agent surface gets a more actionable message."""
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AccountRestrictedError docstring says this is raised when a search returned no results, but via_signsrv.search() also raises it on the explicit code=300011 response path (not necessarily empty results). Please update the docstring to describe the broader contract (account restriction signaled by upstream, including the direct 300011 response case) to avoid misleading future consumers.

Suggested change
"""Raised when a search returned no results because the account itself
is flagged/restricted upstream (e.g. XHS code=300011), distinct from a
generic ChannelAuthError (which means missing/expired credentials). The
fallback chain treats both the same -- switch to the next method -- but
the host agent surface gets a more actionable message."""
"""Raised when the upstream signals the account itself is
flagged/restricted (e.g. XHS code=300011), including explicit
account-restriction responses and cases that may surface as an empty
search result. Distinct from a generic ChannelAuthError (which means
missing/expired credentials). The fallback chain treats both the same
-- switch to the next method -- but the host agent surface gets a more
actionable message."""

Copilot uses AI. Check for mistakes.
Comment on lines +184 to 197
# code=300011: XHS account flagged. Surface as AccountRestrictedError so the
# user sees "your XHS account is restricted, run autosearch login xhs"
# rather than a confusing empty result.
if xhs_code == 300011:
from autosearch.channels.base import ChannelAuthError
from autosearch.channels.base import AccountRestrictedError

LOGGER.warning(
"xhs_account_restricted",
reason="XHS account flagged (code=300011). Run 'autosearch login xhs' with a normal account.",
)
raise ChannelAuthError(
raise AccountRestrictedError(
"XHS account flagged (code=300011). "
"Run 'autosearch login xhs' with a normal account."
)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new AccountRestrictedError raise on the direct xhs_code == 300011 path isn’t covered by the current unit tests (the existing tests only exercise the empty-results + /user/me probe path). Please add a test that simulates the XHS search response returning {"code": 300011, ...} and asserts AccountRestrictedError is raised, so both upgraded raise sites are locked in.

Copilot uses AI. Check for mistakes.
github-actions Bot pushed a commit that referenced this pull request Apr 26, 2026
* docs(security): add P0 deep-scan report from 2026-04-26 6-agent scan

Source-of-truth artifact for the autosearch-0426-p0-deep-scan-fix plan.
Lists 6 P0 findings; P0-5 (release.yml strong gate) was already fixed
in PR #414, so the active fix scope is P0-1 / P0-2 / P0-3 / P0-4 plus
P0-6 hygiene.

* chore(uv): sync uv.lock autosearch self-version to 2026.04.25.11

Main's uv.lock had stale autosearch version 2026.4.25.9 while pyproject
already on 2026.04.25.11 (from PR #416/#417 release bumps). bump-version.sh
doesn't touch uv.lock, so it drifted. Bring back into sync.

Plan F001 S3 (originally planned as 'reset stale residue' — investigation
showed it was a real desync fix worth committing).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants