#23632·keras

Lambda model save/load silently changes numeric constants on Windows

Author: ujwalreddybattu04Created Sep 15, 2026Updated Sep 15, 2026
Labelspythonlayers

Description

On Windows, saving and loading a model containing Lambda(lambda x: x + 92) changes its predictions. The restored function adds 47 instead of 92.

Verified on upstream commit a718e34b9f1fa4998dfba174712613ad0dc37cbc, Keras 3.16.0, Python 3.12.12, Windows, NumPy backend (NumPy 2.5.3, JAX 0.11.1).

Reproduction

import os
import tempfile
from pathlib import Path

os.environ["KERAS_BACKEND"] = "numpy"

import keras
import numpy as np

model = keras.Sequential([
    keras.Input(shape=(1,)),
    keras.layers.Lambda(lambda x: x + 92),
])
x = np.array([[0], [1], [2]], dtype="float32")
before = keras.ops.convert_to_numpy(model(x))
with tempfile.TemporaryDirectory() as directory:
    path = Path(directory) / "model.keras"
    model.save(path)
    # Load only the model created immediately above.
    restored = keras.models.load_model(path, safe_mode=False)
    after = keras.ops.convert_to_numpy(restored(x))

print("Before:", before.ravel().tolist())
print("After: ", after.ravel().tolist())
np.testing.assert_array_equal(after, before)

Expected both outputs: [92.0, 93.0, 94.0].

Actual restored output: [47.0, 48.0, 49.0]. Loading succeeds, but the equality assertion fails.

Cause and proposed fix

The Windows branch in keras/src/utils/python_utils.py::func_dump applies .replace(b"\\", b"/") to the entire marshaled code object. It changes byte 0x5c (92) into 0x2f (47), including numeric constants and string/bytes constants.

The replacement was introduced in #6628 for the old raw_unicode_escape decoder. #8572 subsequently changed the format to Base64. Preserving the marshaled bytes and Base64-encoding them directly fixes the reproduced corruption.

This affects serialized Python functions; it does not imply that every Windows model is affected. The fix prevents new corruption and cannot recover constants already altered in saved artifacts.

Contribution request

I would like to contribute the fix. Could a maintainer assign this issue to @ujwalreddybattu04? A prepared fix and regression tests are in draft PR #23631, pending assignment and the contributor requirements.

Local validation of that fix: 50 tests passed and 3 skipped across the utility, Lambda layer, and object serialization test suites using the NumPy backend. The full model reproduction passes after the fix.

AI assistance was used for investigation, the patch, tests, and this report.