{"record":{"id":"0d71b012e04c0b7b","repo":"NanmiCoder/MediaCrawler","slug":"err-msg","errorCode":null,"errorMessage":"{err_msg}","messagePattern":"\\{err_msg\\}","errorType":"exception","errorClass":"DataFetchError","httpStatus":null,"severity":"error","filePath":"media_platform/xhs/client.py","lineNumber":196,"sourceCode":"        )\n        if response_code == str(self.IP_ERROR_CODE):\n            raise IPBlockError(self.IP_ERROR_STR)\n        if response_code == str(self.SECURITY_LIMIT_CODE):\n            raise PlatformAccessError(\n                f\"XHS account security restriction, code: {self.SECURITY_LIMIT_CODE}\"\n            )\n\n        if return_response:\n            return response.text\n        data: Dict = response_data if response_data is not None else response.json()\n        if data[\"success\"]:\n            return data.get(\"data\", data.get(\"success\", {}))\n        # IP_ERROR_CODE / SECURITY_LIMIT_CODE are already handled above, before return_response.\n        elif data[\"code\"] in (self.NOTE_NOT_FOUND_CODE, self.NOTE_ABNORMAL_CODE):\n            raise NoteNotFoundError(f\"Note not found or abnormal, code: {data['code']}\")\n        else:\n            err_msg = data.get(\"msg\", None) or f\"{response.text}\"\n            raise DataFetchError(err_msg)\n\n    @staticmethod\n    def _build_query_string(params: Dict) -> str:\n        \"\"\"Build URL query string with encoding matching browser behavior (commas not encoded)\"\"\"\n        parts = []\n        for key, value in params.items():\n            value_str = str(value) if value is not None else \"\"\n            parts.append(f\"{key}={quote(value_str, safe=',')}\")\n        return \"&\".join(parts)\n\n    async def get(self, uri: str, params: Optional[Dict] = None) -> Dict:\n        \"\"\"\n        GET request, signs request headers\n        Args:\n            uri: Request route\n            params: Request parameters\n\n        Returns:","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/NanmiCoder/MediaCrawler/blob/d6f7c5bb906b6dac40ddf343ef9e26438a3de092/media_platform/xhs/client.py#L178-L214","documentation":"DataFetchError raised by XiaoHongShuClient.request as the final else branch: the API returned HTTP 200 with a JSON body where success is false, the code is not one of the known special codes, and the message is taken from the response's msg field (falling back to the raw body). It is the catch-all for unrecognized xiaohongshu API errors.","triggerScenarios":"Any xhs API call returning an unexpected business error code - e.g. parameter rejected by the server, unsupported endpoint, or new error codes the client does not special-case. The exact msg string in the exception comes straight from xiaohongshu.","commonSituations":"xiaohongshu adds a new error code after a site update; malformed query built by a wrapper method; semi-logged-in cookie producing error responses on some endpoints only.","solutions":["Read the embedded msg from the exception - it is xiaohongshu's own error text and usually names the problem.","Compare the failing request's params/headers with the same call in a browser devtools session and align them.","If msg indicates login required, refresh the cookie.","Update the client to special-case the new code (like NOTE_NOT_FOUND_CODE) if it recurs across calls."],"exampleFix":"// before\n# generic pass-through\n// after\ntry:\n    data = await xhs_client.get(uri, params=params)\nexcept DataFetchError as e:\n    utils.logger.error(f\"xhs api error for {uri}: {e}\")\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from media_platform.xhs.exception import DataFetchError\ntry:\n    data = await xhs_client.get(uri, params=params)\nexcept DataFetchError as e:\n    utils.logger.error(f\"xhs business error on {uri}: {e}\")\n    raise","preventionTips":["Treat msg text in the exception as the authoritative diagnosis from xiaohongshu.","Mirror browser devtools requests exactly (params, headers, order) when a call keeps failing.","Special-case newly observed codes in the client instead of letting them hit the generic branch."],"tags":["xhs","api-error","data-fetch","catch-all"],"backgroundTag":null,"analyzedSha":"d6f7c5bb906b6dac40ddf343ef9e26438a3de092","analyzedAt":"2026-08-15T01:39:07.505Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}