iflytek/astron-agent · error · ThirdPartyException
(ThirdPartyException ErrorResponse)
Error message
${e.message} (ThirdPartyException ErrorResponse) What it means
handle_rag_operation in core/knowledge/api/v1/api.py wraps RAG operations (file_split, file_upload, chunk_save, chunk_update, chunk_delete, chunk_query) and catches ThirdPartyException separately. It records the exception on the tracing span, increments an error metric with the exception's own code, builds an ad-hoc CodeEnum-like object from e.code/e.message, and returns an ErrorResponse carrying that code and message. The HTTP response surfaces the third-party failure message directly to the caller.
Solutions
- Check the message for which third-party dependency failed and verify that service is reachable (network, DNS, credentials)
- Verify configuration (endpoints, API keys, bucket names) for the failing dependency in the knowledge service config
- Check the tracing span recorded for this request to locate the upstream call that raised
- Add retry/circuit-breaker handling in the third-party adapter if failures are transient
Example fix
// before
return ErrorResponse(code_enum=error_code, message=e.message)
// after
# in the adapter, add context before raising
raise ThirdPartyException(code=e.code, message=f"milvus search failed: {e.message}") Defensive patterns
Strategy: try-catch
Validate before calling
def precheck_dependency(client):
try:
client.health_check(timeout=3)
except Exception as e:
raise PrecheckError(f"third-party dependency unhealthy: {e}") Type guard
def is_thirdparty_error(resp: dict) -> bool:
return isinstance(resp, dict) and resp.get("code") not in (None, 0) and "(ThirdParty)" in str(resp.get("message", "")) Try / catch
try:
resp = rag_api.chunk_query(payload)
except httpx.HTTPError as e:
log.warning("RAG third-party failure: %s", e)
resp = fallback_response(code=getattr(e, 'code', 503)) Prevention
- Health-check vector store/embedding/storage dependencies before request processing
- Configure sensible connect/read timeouts and retries in third-party adapters
- Keep adapter exceptions wrapped in ThirdPartyException with actionable messages
- Alert on metric codes emitted by handle_rag_operation
When it happens
Trigger: Any of the six wrapped RAG API calls invokes a downstream dependency (vector store, embedding service, MinIO, model inference) whose adapter raises ThirdPartyException(code, message).
Common situations: Vector DB unreachable or rejecting the query; embedding endpoint 4xx/5xx; object storage credentials invalid during file_upload; upstream SDK raising wrapped ThirdPartyException on timeout.
Related errors
- (CustomException ErrorResponse)
- Internal server error
- Document splitting failed after retries
- Document splitting failed
- GetFileContentFailed
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/57b3d9adc21ae2ad.
Report an issue: GitHub.
Appendix: source
Thrown at core/knowledge/api/v1/api.py:141
# Basic types, convert to string for consistent handling
span_context.add_info_events({"usr_output": str(result_data)})
else:
# Other types (like custom objects), try to stringify
span_context.add_info_events({"usr_output": str(result_data)})
metric.in_success_count()
return SuccessDataResponse(data=result_data, sid=span_context.sid)
except ProtocolParamException as e:
error_msg = f"{operation_callable.__name__} ProtocolParamException, reason {e}"
logger.error(error_msg)
span_context.record_exception(e)
metric.in_error_count(code=CodeEnum.ParameterCheckException.code)
return ErrorResponse(code_enum=CodeEnum.ParameterCheckException, message=str(e))
except ThirdPartyException as e:
error_msg = f"{operation_callable.__name__} err (ThirdParty), reason {e}"
logger.error(error_msg)
span_context.record_exception(e)
metric.in_error_count(code=e.code)
# Create a CodeEnum-like object for the response
error_code = type("ErrorCode", (), {"code": e.code, "msg": e.message})()
return ErrorResponse(code_enum=error_code, message=e.message)
except CustomException as e:
error_msg = f"{operation_callable.__name__} err (Custom), reason {e}"
logger.error(error_msg)
span_context.record_exception(e)
metric.in_error_count(code=e.code)
# Create a CodeEnum-like object for the response
error_code = type("ErrorCode", (), {"code": e.code, "msg": e.message})()
return ErrorResponse(code_enum=error_code, message=e.message)
except Exception as e: # pylint: disable=W0718
# Intentionally catch all exceptions here as part of global exception handlingView on GitHub (pinned to 5e758547a8)