iflytek/astron-agent · error · CustomException

CodeConvert.sparkLinkCode(code)

CodeConvert.sparkLinkCode(code)

Error message

{response_json.get("header", {}).get("message", "")}

What it means

While processing a SparkLink-format tool response frame, `extract_tool_calls_content` checks the envelope's `header.code`; a non-zero code means the SparkLink tool backend rejected the request. The node raises CustomException with the backend's message and converts the upstream code via `CodeConvert.sparkLinkCode(code)` into a workflow error code.

Solutions

  1. Read header.message in the error to identify the SparkLink-reported cause and fix the tool request parameters or configuration.
  2. Verify the plugin's SparkLink credentials (app id/secret, API key) are valid and not expired.
  3. Check SparkLink service status/quota if the code indicates rate limiting or server error.
  4. Map the returned sparkLinkCode to its documented meaning to apply the right fix (auth vs params vs availability).

Example fix

// before: no pre-check of credentials
call_sparklink_tool(params)

// after: validate config before invocation
if not plugin_config.api_key:
    raise ConfigError("SparkLink API key missing in plugin settings")
if not plugin_config.api_key_valid():
    refresh_credentials()
call_sparklink_tool(params)
Defensive patterns

Strategy: validation

Validate before calling

def sparklink_config_ok(cfg: dict) -> bool:
    return bool(cfg.get("app_id")) and bool(cfg.get("api_key")) and bool(cfg.get("endpoint"))

if not sparklink_config_ok(plugin_config):
    raise ConfigError("SparkLink plugin credentials/endpoint incomplete")

Type guard

def header_indicates_error(frame: dict) -> bool:
    return bool(frame.get("header")) and frame.get("header", {}).get("code", 0) != 0

Try / catch

try:
    result = await run_tool_node(...)
except CustomException as e:
    logger.error(f"SparkLink tool failed: {e.err_msg} (code={e.err_code})")
    if is_auth_code(e.err_code):
        refresh_sparklink_credentials(); result = await retry_once(run_tool_node)
    else:
        raise

Prevention

When it happens

Trigger: process_frame or _process_stream_response -> extract_tool_calls_content on a TOOL-type response containing a `header` with `code != 0` — the SparkLink tool/service returned a business error (auth failure, invalid params, service error, rate limit, etc.).

Common situations: SparkLink app/API key invalid or expired (auth code); malformed tool request parameters; SparkLink service degraded or rate-limited; plugin configured against the wrong SparkLink endpoint or version whose codes changed; quota exhausted on the SparkLink account.

Related errors


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

Appendix: source

Thrown at core/workflow/engine/nodes/util/frame_processor.py:76

    :param tool_calls: List of tool call dictionaries
    :return: Formatted string containing all tool call contents
    :raises CustomException: When tool execution returns error code
    """
    final_content = []
    for tool in tool_calls:
        type_value = str(tool.get("type") or "")
        reason_value = str(tool.get("reason") or "")
        function = cast(Dict[str, Any], tool.get("function") or {})
        response_json_str = function.get("response") or "{}"
        response_json = json.loads(response_json_str)
        if type_value == ToolType.TOOL.value:
            if response_json.get("header"):
                # Handle tool type response
                code = response_json.get("header", {}).get("code")
                if code != 0:
                    err_msg = response_json.get("header", {}).get("message", "")
                    raise CustomException(
                        err_code=CodeConvert.sparkLinkCode(code), err_msg=err_msg
                    )
                payload = response_json.get("payload", {})
                response = payload.get("text", {}).get("text", "")
                response_dict = json.loads(response) if response else {}
            else:
                # Handle MCP (Model Context Protocol) type response
                response_dict = response_json.get("data", {}).get("content", [])
        elif type_value == ToolType.KNOWLEDGE.value:
            response_dict = response_json.get("metadata_list", [])
        # response = function.get("response")
        function_name = str(function.get("name") or "")
        function_arguments = str(function.get("arguments") or "")
        final_content.append(
            generate_agent_output_optimize(
                type_value,
                reason_value,
                response_dict,

View on GitHub (pinned to 5e758547a8)