iflytek/astron-agent · error · CustomException

21601

21601

Error message

can not find main function

What it means

_parser_code_parameter parses the node's Python source with regex to find function signatures and locate the entry point. The engine specifically requires a function named `main`; if none of the matched function definitions is named main (or the regex finds no functions at all), CODE_BUILD_ERROR is raised with 'can not find main function'. The code node contract mandates a main entry function.

Solutions

  1. Rename the entry function to exactly `def main(...):` at module top level.
  2. Ensure main is a plain top-level def (not nested, not a method, no unusual formatting that breaks the regex).
  3. Check that `async def main` is supported for your workflow version; otherwise make it synchronous.
  4. Remove any syntax oddities (decorators on main, weird whitespace) and keep the signature simple.
  5. Debug by running the script locally to confirm it parses, then re-save the node.

Example fix

// before
def run(x):
    return {"out": x}

// after
def main(x):
    return {"out": x}
Defensive patterns

Strategy: validation

Validate before calling

import re
src = code_node_source
matches = re.findall(r"def\s+(\w+)\s*\(([^)]*)\)", src)
if not any(name.strip() == "main" for name, _ in matches):
    raise ValueError("code node must define a top-level 'def main(...)'")

Type guard

def has_main_function(src: str) -> bool:
    import re
    return bool(re.search(r"^\s*def\s+main\s*\(", src, re.M))

Try / catch

try:
    params = code_node._parser_code_parameter(code)
except CustomException as e:
    if e.err_code == CodeEnum.CODE_BUILD_ERROR:
        log.error("code node missing main(): rename entry function to main")
    raise

Prevention

When it happens

Trigger: The code node's script defines only differently-named functions (e.g. `run`, `handler`, `execute`); main is nested inside a class or guarded in a way the regex doesn't match; the script is empty or contains only imports/comments; syntax variations (async def, decorators) break the regex match for the name group.

Common situations: Users pasting scripts from other platforms (which use different entry-point conventions); refactoring renamed main and forgot to update it; snippets with `if __name__ == '__main__'` blocks but no main def; templates using async def main which the parser may not recognize.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at core/workflow/engine/nodes/code/code_node.py:296

    :param python_code: Python code string containing function definitions
    :return: List of parameter names from the main function
    :raises CustomException: If main function is not found in the code
    """
    # Remove comment lines to avoid parsing issues
    python_code = "\n".join(
        line for line in python_code.splitlines() if not line.strip().startswith("#")
    )
    # Regex pattern to match function definitions with optional type hints
    re_pattern = r"def\s+(\w+)\s*\(([^)]*)\)\s*(?:->\s*[\w\[\],\s]*)?:"
    re_matches = re.findall(re_pattern, python_code, re.DOTALL)
    re_parameter: str | None = None
    # Find the main function specifically
    for re_match in re_matches:
        if re_match[0].strip() == "main":
            re_parameter = re_match[1].strip()
            break
    if re_parameter is None:
        raise CustomException(
            CodeEnum.CODE_BUILD_ERROR,
            err_msg="can not find main function",
            cause_error="can not find main function",
        )
    # Split parameters and extract parameter names (remove type hints)
    re_params = re_parameter.split(",")
    variables = []
    for re_param in re_params:
        re_param = re_param.strip()
        if re_param:
            # Remove type hints if present (everything after colon)
            re_param = re_param.split(":")[0].strip()
            variables.append(re_param)
    return variables


class CodeSandboxConfig(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

View on GitHub (pinned to 5e758547a8)