Keras "Invalid filepath extension for saving" (tested fix)

ValueError: Invalid filepath extension for saving. Please add either a `.keras` extension ... or a `.h5` extension comes from Keras 3 when you call model.save("my_model") or .tf. Use model.save("my_model.keras"); for a TensorFlow SavedModel use model.export() and reload it with TFSMLayer. All three are run below.

1. Reproduce

import keras

model = keras.Sequential([keras.Input((4,)), keras.layers.Dense(2)])

for path in ["my_model", "my_model.tf"]:
    try:
        model.save(path)
    except ValueError as e:
        print(f"save({path!r}):", type(e).__name__, "-", str(e))
save('my_model'): ValueError - Invalid filepath extension for saving. Please add either a `.keras` extension for the native Keras format (recommended) or a `.h5` extension. Use `model.export(filepath)` if you want to export a SavedModel for use with TFLite/TFServing/etc. Received: filepath=my_model.
save('my_model.tf'): ValueError - Invalid filepath extension for saving. Please add either a `.keras` extension for the native Keras format (recommended) or a `.h5` extension. Use `model.export(filepath)` if you want to export a SavedModel for use with TFLite/TFServing/etc. Received: filepath=my_model.tf.

Keras 3 picks the format from the extension and only accepts .keras or .h5. A bare directory name (the old TF2 SavedModel default) and .tf both raise this ValueError.

2. Fix: .keras to save, export() for SavedModel

import os
import numpy as np
import keras

model = keras.Sequential([keras.Input((4,)), keras.layers.Dense(2)])
x = np.ones((1, 4), dtype="float32")

model.save("my_model.keras")      # Keras 3 native format
model.save("my_model.h5")         # legacy HDF5, still supported
model.export("my_saved_model")    # TF SavedModel for serving (TF backend)

for p in ["my_model.keras", "my_model.h5"]:
    m = keras.models.load_model(p)
    print(p, "->", type(m).__name__, np.allclose(m(x), model(x)))
print("my_saved_model:", sorted(os.listdir("my_saved_model")))
try:
    keras.models.load_model("my_saved_model")
except ValueError as e:
    print("load_model(SavedModel dir):", str(e))

# To use a SavedModel in Keras 3, wrap it as an inference-only layer:
layer = keras.layers.TFSMLayer("my_saved_model", call_endpoint="serve")
print("TFSMLayer:", np.allclose(layer(x), model(x)))
my_model.keras -> Sequential True
my_model.h5 -> Sequential True
my_saved_model: ['assets', 'fingerprint.pb', 'saved_model.pb', 'variables']
load_model(SavedModel dir): File format not supported: filepath=my_saved_model. Keras 3 only supports V3 `.keras` files, legacy H5 format files (`.h5` extension). Note that the legacy SavedModel format is not supported by `load_model()` in Keras 3. In order to reload a TensorFlow SavedModel as an inference-only layer in Keras 3, use `keras.layers.TFSMLayer(my_saved_model, call_endpoint='serving_default')` (note that your `call_endpoint` might have a different name).
TFSMLayer: True

(The endpoint listing that export() prints was trimmed.)

Related: TensorFlow Keras errors after Keras 3, No module named keras.wrappers.scikit_learn.

Frequently asked questions

Why does model.save say invalid filepath extension?

Keras 3 only saves to paths ending in .keras (native) or .h5 (legacy). A bare folder name or .tf is rejected.

How do I save a SavedModel in Keras 3?

Call model.export("dir"). It writes a TensorFlow SavedModel for serving; model.save no longer does.

How do I load a SavedModel in Keras 3?

load_model does not support it. Use keras.layers.TFSMLayer("dir", call_endpoint="serve") for inference (the endpoint name may be serving_default for older exports).

Written with AI assistance. Measured on 2026-10-24 with tensorflow-cpu 2.21.0, keras 3.15.1 and Python 3.13.5 on Linux. The scripts ran verbatim and the output was pasted unedited except where marked (TensorFlow startup log lines filtered). PlainTables is our extension; Keras and TensorFlow are free.