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

  1. Check the message for which third-party dependency failed and verify that service is reachable (network, DNS, credentials)
  2. Verify configuration (endpoints, API keys, bucket names) for the failing dependency in the knowledge service config
  3. Check the tracing span recorded for this request to locate the upstream call that raised
  4. 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

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


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 handling

View on GitHub (pinned to 5e758547a8)