huggingface/transformers · error · RuntimeError
decompose_prefill_decode expected at least {num_new_tokens}
Error message
decompose_prefill_decode expected at least {num_new_tokens} calls to {type(model).__name__}.forward() during generate(max_new_tokens={num_new_tokens}), but captured {len(calls)}. This likely means generate() bypasses the top-level forward() (e.g. delegates to an inner model), so prefill/decode decomposition is not supported for this architecture. What it means
decompose_prefill_decode instruments the model's top-level forward() and runs generate(max_new_tokens=2 or 3). It expects at least one call per generated token; if fewer forward() calls were captured, generate() is bypassing the top-level forward (delegating to an inner model), so prefill/decode splitting at this level is impossible and the architecture is unsupported.
Source
Thrown at src/transformers/exporters/utils.py:774
# `generation_config` alongside generation kwargs is deprecated. Base it on the model's own config
# when none is given (preserving its defaults), and deep-copy into a distinct `capture_config` so
# the caller's `generation_config` is never mutated.
num_new_tokens = 3 if multi_token_decode else 2
capture_config = copy.deepcopy(generation_config if generation_config is not None else model.generation_config)
capture_config.max_new_tokens = num_new_tokens
capture_config.min_new_tokens = num_new_tokens
try:
with _capture_forward(model) as calls:
model.generate(**copy.deepcopy(inputs), generation_config=capture_config)
except Exception as e:
raise RuntimeError(
f"decompose_prefill_decode failed for {type(model).__name__}. "
f"Inputs passed: {list(inputs.keys())}. "
f"Make sure the inputs are compatible with model.generate()."
) from e
if len(calls) < num_new_tokens:
raise RuntimeError(
f"decompose_prefill_decode expected at least {num_new_tokens} calls to "
f"{type(model).__name__}.forward() during generate(max_new_tokens={num_new_tokens}), but "
f"captured {len(calls)}. This likely means generate() bypasses the top-level forward() "
"(e.g. delegates to an inner model), so prefill/decode decomposition is not supported "
"for this architecture."
)
# Remove `logits_to_keep` from the captured calls — it's a generation-time hint for the model's
# internal top-k pruning, not a forward input. The export graph should not depend on it.
for call in calls:
call.pop("logits_to_keep", None)
# A single-token decode specializes its query-sequence axis to 1 (never dynamic). When
# `multi_token_decode`, merge the two decode steps into one multi-token decode so that axis stays
# symbolic (continuation-from-past, or a plain prefill when the cache is empty, and it still covers seq == 1).
prefill_inputs = calls[0]
decode_inputs = _merge_decode_calls(calls[1:num_new_tokens]) if multi_token_decode else calls[1]
return {View on GitHub (pinned to a597f97485)
Solutions
- Export the inner model directly (e.g. model.model or model.language_model) with decompose_prefill_decode instead of the wrapper
- Check for a transformers update where this architecture's export is supported
- Fall back to exporting a single non-decomposed generation graph if acceptable
Example fix
// before decompose_for_generation(wrapper_model, inputs) // after # export the inner causal LM that generate() actually calls decompose_for_generation(wrapper_model.language_model, inner_inputs)
Defensive patterns
Strategy: fallback
Validate before calling
from transformers.exporters.utils import _capture_forward
def forwards_are_top_level(model, inputs, n=2) -> bool:
with _capture_forward(model) as calls:
model(**inputs)
return len(calls) >= 1 Try / catch
try:
parts = decompose_for_generation(model, inputs)
except RuntimeError as e:
if "bypasses the top-level forward" in str(e):
parts = decompose_for_generation(model.model, inner_inputs) # inner module
else:
raise Prevention
- Check whether generate() calls the wrapper's or an inner forward before exporting
- Prefer exporting the inner causal LM for wrapper architectures
- Track transformers release notes for newly supported export architectures
When it happens
Trigger: Exporting an architecture whose generate() path calls an inner module (e.g. a wrapper model that calls self.model(...)/self.language_model(...)) instead of its own forward; models with custom generate loops or multi-token decode paths that skip the top-level forward.
Common situations: Newly added or custom wrapper architectures in an export pipeline; models refactored so forward() is a thin shim; version changes where generation dispatch moved to inner components.
Related errors
- decompose_prefill_decode failed for {type(model).__name__}.
- Per-component `config` dict is missing entries for: {sorted(
- {type(self).__name__}.export failed on component '{name}' (s
- Found 'model.config.return_loss=True'. Loss computation is n
- Found 'return_loss=True' in inputs. Loss computation is not
AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14).
Data as JSON: /api/errors/945e53733269f43c.
Report an issue: GitHub.