iflytek/astron-agent · error · HTTPClientException

HTTPClientAuthError

HTTPClientAuthError

Error message

ASE 鉴权失败

What it means

The aiohttp client's _auth step signs/refreshes the request URL for the ASE (讯飞开放平台) API. If signing fails to yield a new URL, it raises HTTPClientException with code HTTPClientAuthError and message 'ASE 鉴权失败' (ASE authentication failed).

Solutions

  1. Verify ASE API_KEY/API_SECRET config values are current and correct
  2. Sync server clock (NTP) — signature-based auth is time-sensitive
  3. Re-check signature construction (host/date path) against the ASE auth docs
  4. Confirm the account/endpoint is still active

Example fix

// before
client = AseClient(api_key=os.getenv("OLD_KEY"), api_secret=os.getenv("OLD_SECRET"))
// after
client = AseClient(api_key=os.environ["ASE_API_KEY"], api_secret=os.environ["ASE_API_SECRET"])  # rotated creds
Defensive patterns

Strategy: try-catch

Validate before calling

assert api_key and api_secret, 'ASE_API_KEY/ASE_API_SECRET must be set'
# keep NTP-synced clock; check time skew
import time, ntplib  # ensure offset small

Type guard

def has_ase_creds(cfg) -> bool: return bool(cfg.get('api_key')) and bool(cfg.get('api_secret'))

Try / catch

try:
    resp = await client.request(...)
except HTTPClientException as e:
    if 'ASE' in str(e) and 'auth' in type(e).__name__.lower():
        refresh_credentials(); retry_once()
    raise

Prevention

When it happens

Trigger: request() called with invalid/expired API key/secret, wrong signature algorithm inputs, or system clock skew invalidating the signed URL so new_url comes back None.

Common situations: ASE API key/secret rotated or misconfigured in env; server clock drift; account quota/host change making the auth endpoint reject the signature.

Related errors


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

Appendix: source

Thrown at core/plugin/aitools/common/clients/aiohttp_client.py:152

        self.response: Optional[BaseResponse] = None

    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:
                    self.response = ErrorResponse.from_enum(
                        CodeEnums.HTTPClientAuthError, extra_message="ASE 鉴权失败"
                    )
                    raise HTTPClientException.from_error_code(
                        CodeEnums.HTTPClientAuthError, extra_message="ASE 鉴权失败"
                    )

                self.url = new_url
        except Exception:
            raise

    @asynccontextmanager
    async def start(self) -> AsyncIterator["HttpClient"]:
        """Start aiohttp client"""
        yield self

    @asynccontextmanager
    async def request(self) -> AsyncIterator[BaseResponse]:
        """Send async request and return standardized response"""
        try:
            self._auth()
            session = await get_aiohttp_session()

View on GitHub (pinned to 5e758547a8)