iflytek/astron-agent · error · CustomException
AUDIT_SERVER_ERROR
AUDIT_SERVER_ERROR
Error message
Logic Error: {resp_json} What it means
Raised in _request_with_retry when the IFlyTek audit API returns HTTP 200 but a business code that is neither SUCCESS nor the retryable AUDIT_ERROR code. The library wraps the full response JSON in a CustomException with CodeEnum.AUDIT_SERVER_ERROR, meaning the request was technically fine but the audit service rejected it with a non-recoverable business error.
Solutions
- Inspect the response JSON in the message (resp_json) to read the API's 'code' and 'message' fields and map them to the documented IFlyTek audit error codes.
- Verify chat_app_id, uid, and the auth signature generation in _gen_req_url against IFlyTek console credentials.
- Validate the payload (content length, format of resource_list) against the audit API v3 schema before calling.
- If the code indicates a transient condition, extend ThirdApiCodeEnum handling so it raises NeedRetryException instead of a hard failure.
Example fix
// before: unknown code -> hard failure
raise CustomException(CodeEnum.AUDIT_SERVER_ERROR, cause_error=f"Logic Error: {resp_json}")
// after: log full response and surface the API code
code = int(resp_json.get('code', -1))
logger.error(f"Audit API business error code={code} resp={resp_json}")
raise CustomException(CodeEnum.AUDIT_SERVER_ERROR, cause_error=f"Audit API code={code}: {resp_json.get('message')}") Defensive patterns
Strategy: try-catch
Validate before calling
def audit_payload_ok(payload: dict) -> bool:
return bool(payload) and all(isinstance(k, str) for k in payload) Type guard
def is_success(resp: dict) -> bool:
return isinstance(resp, dict) and int(resp.get('code', -1)) == 0 Try / catch
try:
resp = await audit_api.input_text(content, chat_sid, span)
except CustomException as e:
logger.error(f"audit request rejected: {e}")
raise AuditUnavailable() from e Prevention
- Validate chat_app_id/uid credentials at service startup with a probe request
- Log full audit responses for code-to-meaning mapping
- Keep ThirdApiCodeEnum in sync with the IFlyTek audit API docs
When it happens
Trigger: Calling input_text/output_text/input_media/output_media when the audit API responds with a JSON body whose 'code' is not 0 (SUCCESS) and not the retryable audit-error code — e.g. invalid app id, expired auth signature, malformed payload, or quota/rule violations.
Common situations: Misconfigured chat_app_id or credentials (bad signature embedded in URL), sending payloads with fields the audit service rejects, audit API version changed response codes, or account throttled/rate-limited with a non-retry code.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/313485c9cd082ce2.
Report an issue: GitHub.
Appendix: source
Thrown at core/workflow/infra/audit_system/audit_api/iflytek/ifly_audit_api.py:266
:raises CustomException: If all retry attempts fail or API returns error status
"""
url = self._gen_req_url(f"{host}{path}", chat_app_id, uid)
try:
resp_json = await self._do_request(url, payload)
await span.add_info_event_async(f"Audit response body: {resp_json}")
# Business layer logic judgment
code = int(resp_json.get("code", -1))
if code == ThirdApiCodeEnum.SUCCESS.code:
return resp_json
if code == ThirdApiCodeEnum.AUDIT_ERROR.code:
# Raise specific exception to trigger @retry
raise NeedRetryException(f"Business retry trigger: {code}")
# Other non-recoverable errors
raise CustomException(
CodeEnum.AUDIT_SERVER_ERROR, cause_error=f"Logic Error: {resp_json}"
)
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
span.record_exception(e)
raise # Raise to trigger @retry
async def _post(
self, path: str, payload: dict, span: Span, chat_app_id: str = "", uid: str = ""
) -> dict:
"""
Asynchronously send POST request to audit API and handle response.
Sends authenticated POST requests to the IFlyTek audit API with retry logic
and comprehensive error handling. Supports multiple host endpoints for
high availability.
:param path: API endpoint path to append to the base URLView on GitHub (pinned to 5e758547a8)