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
- 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
- Track metrics via Model.compile(metrics=[...]) where possible
- 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
- Search codebases for add_metric when upgrading to Keras 3
- Create keras.metrics.* trackers in __init__ and call update_state in call/train_step
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
- Argument `num_thresholds` must be an integer > 0. Received:
- Argument `specificity` must be in the range [0, 1]. Received
- Argument `sensitivity` must be in the range [0, 1]. Received
- Argument `recall` must be in the range [0, 1]. Received: rec
- Argument `precision` must be in the range [0, 1]. Received:
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/e9f6622d37cd77df.
Report an issue: GitHub.