NanmiCoder/MediaCrawler · warning · NoteNotFoundError
Note not found or abnormal, code: {data['code']}
Error message
Note not found or abnormal, code: {data['code']} What it means
NoteNotFoundError raised by XiaoHongShuClient.request when the response JSON's code equals -510000 (note not found) or -510001 (note abnormal/deleted). The endpoint answered successfully but reported the requested note is gone, so retrying the same note_id will not help.
Source
Thrown at media_platform/xhs/client.py:193
str(response_data.get("code"))
if response_data is not None and response_data.get("code") is not None
else ""
)
if response_code == str(self.IP_ERROR_CODE):
raise IPBlockError(self.IP_ERROR_STR)
if response_code == str(self.SECURITY_LIMIT_CODE):
raise PlatformAccessError(
f"XHS account security restriction, code: {self.SECURITY_LIMIT_CODE}"
)
if return_response:
return response.text
data: Dict = response_data if response_data is not None else response.json()
if data["success"]:
return data.get("data", data.get("success", {}))
# IP_ERROR_CODE / SECURITY_LIMIT_CODE are already handled above, before return_response.
elif data["code"] in (self.NOTE_NOT_FOUND_CODE, self.NOTE_ABNORMAL_CODE):
raise NoteNotFoundError(f"Note not found or abnormal, code: {data['code']}")
else:
err_msg = data.get("msg", None) or f"{response.text}"
raise DataFetchError(err_msg)
@staticmethod
def _build_query_string(params: Dict) -> str:
"""Build URL query string with encoding matching browser behavior (commas not encoded)"""
parts = []
for key, value in params.items():
value_str = str(value) if value is not None else ""
parts.append(f"{key}={quote(value_str, safe=',')}")
return "&".join(parts)
async def get(self, uri: str, params: Optional[Dict] = None) -> Dict:
"""
GET request, signs request headers
Args:
uri: Request routeView on GitHub (pinned to d6f7c5bb90)
Solutions
- Treat as terminal for that note: catch NoteNotFoundError, log, and continue the crawl.
- If it happens for every note, suspect an expired or wrong xsec_token being passed and re-fetch search results to get fresh tokens.
- Filter note IDs by publish recency to avoid fetching already-removed content.
- Do not retry the same note_id - these codes are deterministic.
Example fix
// before
note = await xhs_client.get_note_by_id(note_id)
// after
from media_platform.xhs.exception import NoteNotFoundError
try:
note = await xhs_client.get_note_by_id(note_id)
except NoteNotFoundError:
utils.logger.info(f"note {note_id} gone, skipping")
note = None Defensive patterns
Strategy: try-catch
Try / catch
from media_platform.xhs.exception import NoteNotFoundError
try:
note = await xhs_client.get_note_by_id(note_id)
except NoteNotFoundError:
utils.logger.info(f"note {note_id} deleted/abnormal - skipped")
note = None Prevention
- Never retry on -510000/-510001 - the note is gone.
- Pass fresh xsec_token values from current search results when fetching note details.
- Prefer recently published notes to reduce mid-crawl deletions.
When it happens
Trigger: Calling get_note_by_id (or comment APIs) with a note_id that was deleted, set to private, or removed by moderation after it was discovered by search/creator crawling.
Common situations: Long crawls where search results contain notes deleted before their detail fetch; note links shared from other users whose authors later deleted them; xsec_token mismatch causing the API to treat the note as inaccessible.
Related errors
- {err_msg}
- get weibo detail err: {response.text}
- get containerid failed
- Get creator info error
- params or payload is required
AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15).
Data as JSON: /api/errors/2538c4407a05ac0f.
Report an issue: GitHub.