keras-team/keras · error · TypeError

`backend_variable` must be a `backend.Variable`. Recevied: b

Error message

`backend_variable` must be a `backend.Variable`. Recevied: backend_variable={backend_variable} of type ({type(backend_variable)})

What it means

Raised by ExportArchive._convert_to_tf_variable when a value passed into the SavedModel export path is not a keras.backend.Variable. The exporter walks model weights and converts each one to a tf.Variable, so any weight-like object that is not a Keras Variable (e.g. a raw tf.Variable, a numpy array, or a tensor) triggers this TypeError. It almost always means the model contains manually attached non-Keras weights or was built with a non-TensorFlow Keras backend (jax/torch) whose variables are not instances of backend.Variable in the TF backend namespace.

Source

Thrown at keras/src/export/saved_model_export_archive.py:303

        )

        # Print out available endpoints
        if verbose:
            endpoints = "\n\n".join(
                _print_signature(
                    getattr(self._tf_trackable, name), name, verbose=verbose
                )
                for name in self._endpoint_names
            )
            io_utils.print_msg(
                f"Saved artifact at '{filepath}'. "
                "The following endpoints are available:\n\n"
                f"{endpoints}"
            )

    def _convert_to_tf_variable(self, backend_variable):
        if not isinstance(backend_variable, backend.Variable):
            raise TypeError(
                "`backend_variable` must be a `backend.Variable`. "
                f"Recevied: backend_variable={backend_variable} of type "
                f"({type(backend_variable)})"
            )
        return tf.Variable(
            backend_variable.value,
            dtype=backend_variable.dtype,
            trainable=backend_variable.trainable,
            name=backend_variable.name,
        )

    def _get_concrete_fn(self, endpoint):
        """Workaround for some SavedModel quirks."""
        if endpoint in self._endpoint_signatures:
            return getattr(self._tf_trackable, endpoint)
        else:
            traces = getattr(self._tf_trackable, endpoint)._trackable_children(
                "saved_model"

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Ensure the model is built and its weights created under the TensorFlow backend: set os.environ['KERAS_BACKEND']='tensorflow' before importing keras, then rebuild the model.
  2. Replace any manually attached tf.Variable or numpy weights on layers with proper Keras variables via keras.Variable(...) or layer.add_weight(...).
  3. If exporting from torch/jax, first convert weights: rebuild the same architecture on the TF backend and load_weights() from the saved checkpoint before exporting.

Example fix

# before
self.scale = tf.Variable(1.0)  # raw TF variable on a Keras layer
archive.track(model)  # -> TypeError in _convert_to_tf_variable

# after
self.scale = keras.Variable(1.0)  # keras.src.backend.Variable
archive.track(model)
Defensive patterns

Strategy: type-guard

Validate before calling

import keras
from keras.src import backend

def is_keras_variable(w):
    return isinstance(w, backend.Variable)

Type guard

from keras.src import backend

def is_keras_variable(w) -> bool:
    return isinstance(w, backend.Variable)

Prevention

When it happens

Trigger: Calling export_archive.track(model) or ExportArchive(...) on a model whose weights include raw tf.Variable objects, numpy arrays, or variables created under keras.backend('jax') or ('torch') while exporting to a TensorFlow SavedModel; also directly calling archive._convert_to_tf_variable(non_variable).

Common situations: Mixed TF/Keras 3 code where users assign tf.Variable attributes to layers; exporting a model built with the JAX or PyTorch multi-backend and then trying to write a TF SavedModel; porting Keras 2 code that manipulated weights as numpy arrays.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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