keras-team/keras · error · NotImplementedError

Layer `add_metric()` method is deprecated. Add your metric i

Error message

Layer `add_metric()` method is deprecated. Add your metric in `Model.compile(metrics=[...])`, or create metric trackers in init() or build() when subclassing the layer or model, then call `metric.update_state()` whenever necessary.

What it means

Keras 3 permanently removed Layer.add_metric(). Calling it always raises NotImplementedError with guidance: track metrics via Model.compile(metrics=[...]) or create metric tracker objects (e.g. keras.metrics.Mean) in __init__/build and call update_state() in call().

Source

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

        if variable.trainable:
            self._tracker.add_to_store("trainable_variables", variable)
        else:
            self._tracker.add_to_store("non_trainable_variables", variable)
        if not self.trainable:
            variable.trainable = False
        self._post_track_variable(variable)

    def _untrack_variable(self, variable):
        previous_lock_state = self._tracker.locked
        self._tracker.unlock()
        self._tracker.untrack(variable)
        if previous_lock_state is True:
            self._tracker.lock()
        self._post_untrack_variable(variable)

    def add_metric(self, *args, **kwargs):
        # Permanently disabled
        raise NotImplementedError(
            "Layer `add_metric()` method is deprecated. "
            "Add your metric in `Model.compile(metrics=[...])`, "
            "or create metric trackers in init() or build() "
            "when subclassing the layer or model, then call "
            "`metric.update_state()` whenever necessary."
        )

    def count_params(self):
        """Count the total number of scalars composing the weights.

        Returns:
            An integer count.
        """
        if not self.built:
            raise ValueError(
                "You tried to call `count_params` "
                f"on layer '{self.name}', "
                "but the layer isn't built. "

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Create metric objects in __init__ (self.mae_metric = keras.metrics.MeanAbsoluteError(name='mae')) and call self.mae_metric.update_state(y, y_pred) in call/train_step
  2. Track metrics via Model.compile(metrics=[...]) where possible
  3. Delete all add_metric call sites when porting

Example fix

# before
def call(self, x):
    self.add_loss(self.reg_loss(x))
    self.add_metric(self.reg_loss(x), name='reg')
# after
def __init__(self, **kw):
    super().__init__(**kw)
    self.reg_metric = keras.metrics.Mean(name='reg')
def call(self, x):
    self.reg_metric.update_state(self.reg_loss(x))
    return x
Defensive patterns

Strategy: validation

Validate before calling

# static migration: grep for add_metric and replace with metric trackers

Prevention

When it happens

Trigger: Any call to self.add_metric(value, name=...) in subclassed layers ported from Keras 2 or TF2.

Common situations: Migrating Keras 2 custom layers and models to Keras 3; old tutorials using add_metric inside call().

Related errors


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