iflytek/astron-agent · error · CustomException

SPARK_FUNCTION_NOT_CHOICE_ERROR

SPARK_FUNCTION_NOT_CHOICE_ERROR

Error message

Cannot find function_call field in LLM response

What it means

This CustomException (SPARK_FUNCTION_NOT_CHOICE_ERROR) is raised by the iFlytek Spark function-calling client when the final WebSocket frame (header.status == 2) arrives but the model's reply text entry lacks a 'function_call' key. It means Spark answered with plain content instead of selecting one of the supplied functions, so the caller cannot extract a function name/arguments.

Solutions

  1. Check the frame payload in the tracing span (function_call_recv event) to confirm the final frame really has no function_call field
  2. Ensure a non-empty, schema-valid functions list is passed to async_call_spark_fc and that descriptions clearly indicate when to call each function
  3. Rephrase the user prompt so it clearly requests an action the functions can perform, or adjust temperature/top_k
  4. If a text answer (no function call) is legitimate for your flow, handle the None/missing case instead of treating it as an error

Example fix

// before
name, usage, arguments = await await_spark_fc(user_input, functions)
// after
try:
    name, usage, arguments = await await_spark_fc(user_input, functions)
except CustomException as e:
    if e.err_code == CodeEnum.SPARK_FUNCTION_NOT_CHOICE_ERROR:
        fallback_answer = await plain_chat(user_input)
    else:
        raise
Defensive patterns

Strategy: fallback

Validate before calling

def functions_ready(functions):
    return bool(functions) and all(f.get('name') and f.get('description') for f in functions)
if not functions_ready(function_list):
    raise ValueError('functions list must be non-empty with name+description')

Type guard

def has_function_call(msg: dict) -> bool:
    choices = msg.get('payload', {}).get('choices', {}).get('text', [])
    return bool(choices) and 'function_call' in choices[0]

Try / catch

try:
    name, usage, args = await spark_fc.async_call_spark_fc(user_input, span)
except CustomException as e:
    if e.err_code == CodeEnum.SPARK_FUNCTION_NOT_CHOICE_ERROR:
        name, usage, args = None, None, None
    else:
        raise

Prevention

When it happens

Trigger: In _recv_messages/_process_message: header.code == 0, header.status == 2 (final frame), but 'function_call' not in msg['payload']['choices']['text'][0] — i.e. the model chose not to call any function or returned a normal text answer.

Common situations: User prompt doesn't match any registered function; functions array sent empty or malformed; temperature/top_k tuned so the model prefers free text; Spark content filtering stripped the function decision; prompt history nudges the model toward conversational replies.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at core/workflow/infra/providers/llm/iflytek_spark/spark_fc_llm.py:125

                if code != 0:
                    raise CustomException(
                        err_code=CodeConvert.sparkCode(code),
                        cause_error=json.dumps(msg, ensure_ascii=False),
                    )
                status = msg["header"]["status"]
                llm_service_sid = msg["header"]["sid"]
                # Check if it's a quick repair: if the last character of sid is '1', it's a quick repair
                if llm_service_sid[-1] == "1":
                    raise CustomException(
                        err_code=CodeEnum.SPARK_QUICK_REPAIR_ERROR,
                        err_msg="Sensitive content detected, LLM did not find function_call field",
                        cause_error="Sensitive content detected, LLM did not find function_call field",
                    )
                if status != 2:
                    continue
                token_usage = msg["payload"]["usage"]["text"]
                if "function_call" not in msg["payload"]["choices"]["text"][0]:
                    raise CustomException(
                        err_code=CodeEnum.SPARK_FUNCTION_NOT_CHOICE_ERROR,
                        err_msg="Cannot find function_call field in LLM response",
                        cause_error="Cannot find function_call field in LLM response",
                    )

                name = msg["payload"]["choices"]["text"][0]["function_call"]["name"]
                arguments = msg["payload"]["choices"]["text"][0]["function_call"][
                    "arguments"
                ]
                return name, token_usage, arguments
            except websockets.ConnectionClosed:
                raise CustomException(
                    err_code=CodeEnum.SPARK_REQUEST_ERROR,
                    err_msg="WebSocket connection closed",
                    cause_error="WebSocket connection closed",
                )
            except Exception as e:
                raise CustomException(

View on GitHub (pinned to 5e758547a8)