vllm-project/vllm · error · RuntimeError

call_module is not allowed for codegen target {target}.

Error message

call_module is not allowed for codegen target {target}.

What it means

The FX-graph code generator turns a split GraphModule back into plain Python source. After splitting, nodes should be call_function/getattr/placeholder/output; encountering a call_module node (an un-inlined submodule) is only legal when with_submod=True (which emits the submodule as an inlined closure). With with_submod=False the code generator cannot reference the module, so it raises RuntimeError naming the offending target.

Source

Thrown at vllm/compilation/codegen.py:67

        users = list(node.users.keys())
        if not users:
            continue
        last_user = max(users, key=lambda u: node_order[u])
        if last_user.op == "output":
            continue
        del_after.setdefault(node_order[last_user], []).append(node.name)

    def ref(arg: Any) -> str:
        return _node_ref(arg, consts, const_index)

    for i, node in enumerate(nodes):
        if node.op == "placeholder":
            param_names.append(node.name)

        elif node.op == "call_module":
            target = node.target
            if not with_submod:
                raise RuntimeError(
                    f"call_module is not allowed for codegen target {target}."
                )
            if target not in submod_index:
                submod_index[target] = len(submod_names)
                submod_names.append(target)
            idx = submod_index[target]
            args_str = ", ".join(ref(a) for a in node.args)
            kwargs_str = ", ".join(f"{k}={ref(v)}" for k, v in node.kwargs.items())
            all_args = ", ".join(filter(None, [args_str, kwargs_str]))
            submod = getattr(split_gm, target)
            if isinstance(submod, torch.fx.GraphModule):
                callable_name = f"__vllm_inlined_submods__{idx}"
                inlined_code, _, _ = generate_execution_code_with_name(
                    submod,
                    callable_name,
                    with_submod=False,
                    consts=consts,
                    const_index=const_index,

View on GitHub (pinned to c794754062)

Solutions

  1. Pass with_submod=True so call_module nodes are emitted as inlined submodule closures
  2. Re-split the graph (split_gm) so module calls are lowered before codegen
  3. If tracing from model code, refactor the module into functional calls dynamo can inline, or report a vLLM bug with the graph

Example fix

# before
code = codegen(fn_name, nodes, split_gm, consts, with_submod=False)
# after
code = codegen(fn_name, nodes, split_gm, consts, with_submod=True)
Defensive patterns

Strategy: validation

Validate before calling

bad = [n for n in graph.nodes if n.op == "call_module"]
assert with_submod or not bad, f"graph still has call_module nodes: {[n.target for n in bad]}"

Type guard

def codegen_ready(graph: torch.fx.Graph, with_submod: bool) -> bool:
    return with_submod or all(n.op != "call_module" for n in graph.nodes)

Prevention

When it happens

Trigger: Calling the codegen helper on a graph that still contains call_module nodes (not fully traced/inlined by dynamo, e.g. a module boundary dynamo did not inline) with with_submod=False.

Common situations: Model code with modules that dynamo fails to trace (custom Module subclasses with __call__ side effects, module-level state), or internal callers invoking the codegen utility on unsplit graphs; usually a vLLM/torch version-compat issue rather than a user config error.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/90d799ac94f76f11. Report an issue: GitHub.