{"record":{"id":"b74d4616380cdbd9","repo":"keras-team/keras","slug":"add-loss-can-only-be-called-from-inside-build","errorCode":null,"errorMessage":"`add_loss()` can only be called from inside `build()` or `call()`, on a tensor input. Received invalid value: {x}","messagePattern":"`add_loss\\(\\)` can only be called from inside `build\\(\\)` or `call\\(\\)`, on a tensor input\\. Received invalid value: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/layer.py","lineNumber":1292,"sourceCode":"\n    def add_loss(self, loss):\n        \"\"\"Can be called inside of the `call()` method to add a scalar loss.\n\n        Example:\n\n        ```python\n        class MyLayer(Layer):\n            ...\n            def call(self, x):\n                self.add_loss(ops.sum(x))\n                return x\n        ```\n        \"\"\"\n        # Eager only.\n        losses = tree.flatten(loss)\n        for x in losses:\n            if not backend.is_tensor(x):\n                raise ValueError(\n                    \"`add_loss()` can only be called from inside `build()` or \"\n                    f\"`call()`, on a tensor input. Received invalid value: {x}\"\n                )\n        if backend.in_stateless_scope():\n            scope = backend.get_stateless_scope()\n            if scope.collect_losses:\n                for x in losses:\n                    scope.add_loss(x)\n                    self._loss_ids.add(id(x))\n        else:\n            self._losses.extend(losses)\n\n    def _get_own_losses(self):\n        if backend.in_stateless_scope():\n            losses = []\n            scope = backend.get_stateless_scope()\n            for loss in scope.losses:\n                if id(loss) in self._loss_ids:","sourceCodeStart":1274,"sourceCodeEnd":1310,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/layer.py#L1274-L1310","documentation":"add_loss() accepts only backend tensors. It is meant to be called inside build() or call(); passing Python numbers, NumPy arrays, or anything that is not a backend tensor raises this eager-mode validation error.","triggerScenarios":"self.add_loss(0.01 * self.l2) where the value is a Python float/np.ndarray; add_loss(np.array(...)); calling add_loss outside call/build with computed Python scalars.","commonSituations":"Regularization losses computed with NumPy instead of keras.ops; porting TF1/TF2 code that added float losses; debug code adding constants.","solutions":["Wrap values with keras.ops.convert_to_tensor (or use keras.ops operations throughout) before add_loss","Compute losses from layer tensors/variables so the result stays a backend tensor"],"exampleFix":"# before\nself.add_loss(1e-4 * np.sum(w))\n# after\nimport keras\nself.add_loss(1e-4 * keras.ops.sum(keras.ops.convert_to_tensor(w)))","handlingStrategy":"validation","validationCode":"import keras\nlosses = [keras.ops.convert_to_tensor(l) for l in losses]\nlayer.add_loss(losses)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute losses with keras.ops so results stay backend tensors","Never add Python/NumPy scalars via add_loss"],"tags":["keras","layers","add-loss","tensor-validation"],"backgroundTag":"non-tensor-value-passed","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}