keras-team/keras · error · RuntimeError

Cannot add call-context args after the layer has been called

Error message

Cannot add call-context args after the layer has been called.

What it means

Raised by Layer._register_call_context_args when you try to declare new call-context argument names after the layer has already been executed at least once. Keras records call-context args (custom keyword arguments passed through __call__) at build/spec time, and once self._called is True the call signature is frozen, so late registration is rejected to keep compute_output_spec and call dispatch consistent.

Source

Thrown at keras/src/layers/layer.py:1881

            def call(self, x):
                # We don't explicitly pass foo_mode here—Base Layer.__call__
                # should inject it into `self.inner`
                return self.inner(x)

        sample_input = np.array([[1.0], [2.0]])

        # Sequential model
        seq = models.Sequential([Outer()])

        # Tell the Sequential model to propagate foo_mode down
        # the call-stack
        seq._register_call_context_args("foo_mode")

        # foo_mode=True -> input + 1
        out_true = seq(sample_input, foo_mode=True)
        """
        if self._called:
            raise RuntimeError(
                "Cannot add call-context args after the layer has been called."
            )
        self._call_context_args = self._call_context_args | set(names)

        self._call_has_context_arg.update(
            {arg: (arg in self.call_signature_parameters) for arg in names}
        )


def is_backend_tensor_or_symbolic(x, allow_none=False):
    if allow_none and x is None:
        return True
    return backend.is_tensor(x) or isinstance(x, backend.KerasTensor)


class CallSpec:
    def __init__(self, signature, call_context_args, args, kwargs):
        # Strip out user-supplied call-context args that this layer’s `call()`

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Move the _register_call_context_args(...) call into __init__ (or before the first __call__) so registration precedes any execution
  2. If wrapping sublayers, register context args on each sublayer at construction time, not inside the wrapper's call()
  3. If the model was already called, create a fresh instance (or re-instantiate the layer) and register the args before invoking it

Example fix

# before
seq(sample_input)
seq._register_call_context_args('foo_mode')  # RuntimeError

# after
class MyLayer(keras.layers.Layer):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._register_call_context_args('foo_mode')
    def call(self, inputs, foo_mode=False):
        ...
out = seq(sample_input, foo_mode=True)
Defensive patterns

Strategy: validation

Validate before calling

if layer._called:
    raise RuntimeError('register context args before calling the layer')

Type guard

def can_register(layer) -> bool:
    return not getattr(layer, '_called', False)

Prevention

When it happens

Trigger: Calling layer._register_call_context_args('foo_mode') (directly or via a wrapper like a Functional/Sequential model that registers context args on its sublayers) after the layer or an enclosing model has already been invoked, e.g. seq(sample_input) followed by seq._register_call_context_args(...).

Common situations: Building a wrapper layer that lazily registers context args inside call() instead of __init__; mutating a shared/serialized model after inference; reusing a loaded model and then adding new context kwargs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/db8f55b6ab0ee537. Report an issue: GitHub.