huggingface/transformers · error · NotImplementedError

StoppingCriteria needs to be subclassed

Error message

StoppingCriteria needs to be subclassed

What it means

NotImplementedError raised by the abstract StoppingCriteria.__call__ in transformers/generation/stopping_criteria.py. StoppingCriteria is an ABC-style base class; its __call__ intentionally raises so that any criteria object used in generate(stopping_criteria=...) must override __call__. You get this when the base class (or a subclass that forgot to override __call__) is actually invoked.

Source

Thrown at src/transformers/generation/stopping_criteria.py:55

    Return:
        `torch.BoolTensor`. (`torch.BoolTensor` of shape `(batch_size, 1)`):
            `True` indicates we stop generation for a particular row.
            `False` indicates we should continue.

"""


class StoppingCriteria(ABC):
    """Abstract base class for all stopping criteria that can be applied during generation.

    If your stopping criteria depends on the `scores` input, make sure you pass `return_dict_in_generate=True,
    output_scores=True` to `generate`.
    """

    @add_start_docstrings(STOPPING_CRITERIA_INPUTS_DOCSTRING)
    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> torch.BoolTensor:
        raise NotImplementedError("StoppingCriteria needs to be subclassed")


class MaxLengthCriteria(StoppingCriteria):
    """
    This class can be used to stop generation whenever the full generated number of tokens exceeds `max_length`. Keep
    in mind for decoder-only type of transformers, this will include the initial prompted tokens.

    Args:
        max_length (`int`):
            The maximum length that the output sequence can have in number of tokens.
        max_position_embeddings (`int`, *optional*):
            The maximum model length, as defined by the model's `config.max_position_embeddings` attribute.
    """

    def __init__(self, max_length: int, max_position_embeddings: int | None = None):
        self.max_length = max_length
        self.max_position_embeddings = max_position_embeddings

View on GitHub (pinned to a597f97485)

Solutions

  1. Subclass StoppingCriteria and implement __call__(self, input_ids, scores, **kwargs) -> torch.BoolTensor returning a per-batch bool tensor.
  2. Alternatively subclass an existing concrete criteria (e.g. StopStringCriteria, MaxLengthCriteria) and override its logic.
  3. Never pass the bare StoppingCriteria instance into generate().

Example fix

# before
class MyStop(StoppingCriteria):
    def check(self, input_ids, scores, **kwargs):  # wrong name
        return input_ids.shape[1] > 50

# after
class MyStop(StoppingCriteria):
    def __call__(self, input_ids, scores, **kwargs):
        return input_ids.shape[1] > 50 * torch.ones(input_ids.shape[0], dtype=torch.bool, device=input_ids.device)
Defensive patterns

Strategy: type-guard

Type guard

def is_usable_stopping_criteria(c) -> bool:
    return (
        not type(c).__name__ == "StoppingCriteria"
        and callable(getattr(c, "__call__", None))
        and type(c).__call__ is not StoppingCriteria.__call__
    )

Prevention

When it happens

Trigger: Instantiating StoppingCriteria() directly and passing it to generate(); subclassing StoppingCriteria but naming the method something else (e.g. __call__(self, input_ids, scores) misspelled, or defining call() instead of __call__); subclassing a criteria like MaxLengthCriteria but overriding __init__ only.

Common situations: Writing a custom stop-on-keyword criteria and forgetting the exact __call__(self, input_ids, scores, **kwargs) signature; renaming during refactor so Python resolves to the base __call__.

Related errors


AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14). Data as JSON: /api/errors/6c72c4c17112d9ce. Report an issue: GitHub.