{"record":{"id":"723a431e89042d88","repo":"jd-opensource/joyagent-jdgenie","slug":"error-723a43","errorCode":null,"errorMessage":"认证失败 - 无效的凭据","messagePattern":"认证失败 - 无效的凭据","errorType":"exception","errorClass":"Exception","httpStatus":401,"severity":"error","filePath":"genie-client/app/client.py","lineNumber":146,"sourceCode":"            streams = await self._streams_context.__aenter__()\n            logger.debug(f\"[{connection_id}] SSE流连接已建立\")\n\n            # 创建客户端会话\n            self._session_context = ClientSession(*streams)\n            session = await self._session_context.__aenter__()\n            logger.debug(f\"[{connection_id}] 客户端会话已创建\")\n\n            # 初始化会话，可能触发认证验证\n            await session.initialize()\n            logger.info(f\"[{connection_id}] SSE连接建立成功\")\n\n            yield session\n\n        except Exception as e:\n            # 根据异常类型进行不同的处理\n            if self._is_authentication_error(e):\n                logger.error(f\"[{connection_id}] 认证失败 - 401 未授权\")\n                raise Exception(\"认证失败 - 无效的凭据\") from e\n            elif self._is_network_error(e):\n                logger.error(f\"[{connection_id}] 网络连接失败: {str(e)}\")\n                raise Exception(f\"网络连接失败: {str(e)}\") from e\n            else:\n                logger.error(f\"[{connection_id}] SSE连接失败: {str(e)}\")\n                raise\n        finally:\n            # 确保资源被正确清理\n            await self._cleanup_connection(connection_id)\n\n    @staticmethod\n    def _is_authentication_error(exception: Exception) -> bool:\n        \"\"\"\n        检查异常是否为认证错误 (401 Unauthorized)\n\n        Args:\n            exception: 待检查的异常对象\n","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-client/app/client.py#L128-L164","documentation":"Raised by `_sse_connection` in the MCP SSE client when the server responds with an authentication failure (401) during the SSE handshake. The original exception is inspected by `_is_authentication_error` and re-raised as a generic Exception with this message. It means the configured credentials (API key/token) are missing, malformed, or rejected by the server.","triggerScenarios":"Any of ping_server, list_tools, or call_tool opens an SSE session (`_sse_connection`) while the HTTP connection is rejected with 401 Unauthorized — e.g. expired/invalid API key, wrong auth header, or server auth policy change.","commonSituations":"Environment variable holding the token not set or pointing at the wrong server; token rotated or revoked upstream; missing `Authorization` header configuration in the client constructor; using a staging token against production.","solutions":["Verify the API key/token configured on the client (constructor/headers) is current and correct for this server_url","Check the Authorization header is actually being attached (log or inspect the client config before connect)","Curl the SSE endpoint manually with the same header to confirm the credential works outside the library","Re-generate or rotate credentials from the server admin console and restart the client"],"exampleFix":"// before\nclient = SseClient(server_url=URL)  # no auth headers\n// after\nclient = SseClient(server_url=URL, headers={\"Authorization\": f\"Bearer {os.environ['MCP_TOKEN']}\"})","handlingStrategy":"try-catch","validationCode":"token = os.environ.get(\"MCP_TOKEN\")\nif not token:\n    raise RuntimeError(\"MCP_TOKEN not set\")\n# optionally: curl the endpoint with the header before connecting","typeGuard":"def has_credentials(client) -> bool:\n    return bool(getattr(client, \"headers\", {}).get(\"Authorization\"))","tryCatchPattern":"try:\n    await client.ping_server()\nexcept Exception as e:\n    if \"认证失败\" in str(e):\n        refresh_credentials_and_retry()\n    else:\n        raise","preventionTips":["Load credentials from env/config at startup and fail fast if missing","Rotate tokens before expiry and restart dependent clients","Test auth with a cheap ping_server call before heavier operations"],"tags":["authentication","http-401","sse"],"backgroundTag":"authentication-required","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}