iflytek/astron-agent · error · WebSocketClientException

WebSocketClientAuthError

WebSocketClientAuthError

Error message

ASE 鉴权失败

What it means

WebSocketClientAuthError (via WebSocketClientException.from_error_code) raised in WebSocketClient._auth when HMACAuth.build_auth_request_url returns None, meaning the ASE HMAC signature could not be built for the WebSocket URL. In practice this happens when the API key or secret passed to the constructor is missing/empty or the auth URL construction fails, so the signed URL is never produced and the client aborts at construction time.

Solutions

  1. Verify you pass non-empty api_key and api_secret kwargs: WebSocketClient(url, auth='ASE', api_key=os.environ['ASE_API_KEY'], api_secret=os.environ['ASE_API_SECRET'])
  2. Log/inspect the kwargs reaching _auth — a typo in the kwarg name silently falls back to '' via self.kwargs.get('api_key', '')
  3. Confirm the credentials are valid and active in the ASE console; regenerate if revoked
  4. Check that self.url is a well-formed ws:// or wss:// URL that HMACAuth.build_auth_request_url can sign

Example fix

// before
client = WebSocketClient(url, auth="ASE")  # no api_key/api_secret -> build_auth_request_url returns None
// after
client = WebSocketClient(
    url,
    auth="ASE",
    api_key=os.environ["ASE_API_KEY"],
    api_secret=os.environ["ASE_API_SECRET"],
    method="GET",
)
Defensive patterns

Strategy: try-catch

Validate before calling

def ase_credentials_ready(kwargs: dict) -> bool:
    return bool(kwargs.get("auth") == "ASE"
                and kwargs.get("api_key")
                and kwargs.get("api_secret"))

Try / catch

from plugin.aitools.common.clients.exceptions import WebSocketClientException  # adjust import to project layout
try:
    client = WebSocketClient(url, auth="ASE", api_key=key, api_secret=secret)
except WebSocketClientException as e:
    log.error("ASE WebSocket auth failed; check api_key/api_secret kwargs: %s", e)
    raise

Prevention

When it happens

Trigger: Constructing WebSocketClient(url, auth='ASE') where the 'api_key'/'api_secret' kwargs are absent, empty strings (the .get(..., "") defaults), or contain characters HMACAuth cannot sign; also when self.url is malformed such that build_auth_request_url fails and returns None.

Common situations: Missing API key/secret in environment or config after a deployment; renamed kwarg (e.g. passing 'apiKey' instead of 'api_key') so the default '' kicks in; expired or revoked ASE credentials; wrong auth method value while auth='ASE' is still set.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/e9bce3b94f68649c. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/aitools/common/clients/websockets_client.py:86

        """Start async WebSocket client"""
        await self.connect()
        yield self

    def _auth(self) -> None:
        """Build WebSocket URL"""
        try:
            if "auth" in self.kwargs and self.kwargs["auth"] == "ASE":

                method = self.kwargs.get("method", "GET")
                api_key = self.kwargs.get("api_key", "")
                api_secret = self.kwargs.get("api_secret", "")
                new_url = HMACAuth.build_auth_request_url(
                    self.url, method, api_key, api_secret
                )

                if new_url is None:
                    log.error("WebSocket auth failed")
                    raise WebSocketClientException.from_error_code(
                        CodeEnums.WebSocketClientAuthError, extra_message="ASE 鉴权失败"
                    )

                self.url = new_url
        except Exception:
            raise

    async def connect(self) -> None:
        """Connect to WebSocket server"""
        try:
            self.ws = await websockets.connect(self.url, **self.ws_params)
            self._running = True
        except Exception as e:
            raise WebSocketClientException.from_error_code(
                CodeEnums.WebSocketClientNotConnectedError, extra_message=str(e)
            )

        self._tasks.append(self.task_factory.create(self._send_loop()))

View on GitHub (pinned to 5e758547a8)