keras-team/keras · error · ValueError
Requested the deserialization of a `TFSMLayer`, which loads
Error message
Requested the deserialization of a `TFSMLayer`, which loads an external SavedModel. This carries a potential risk of arbitrary code execution and thus it is disallowed by default. If you trust the source of the artifact, you can override this error by passing `safe_mode=False` to the loading function, or calling `keras.config.enable_unsafe_deserialization().
What it means
Deserializing a TFSMLayer (TFSMLayer.from_config, reached via keras.layers.deserialize or model loading) reloads an external SavedModel, which can execute arbitrary code. Keras therefore refuses by default: if safe_mode is not explicitly False, and global keras.config.enable_unsafe_deserialization() was not called, from_config raises this ValueError. It is a deliberate supply-chain guard, not a bug.
Source
Thrown at keras/src/export/tfsm_layer.py:172
Args:
config: A Python dictionary, typically the output of `get_config`.
custom_objects: Optional dictionary mapping names to custom objects.
safe_mode: Boolean, whether to disallow loading TFSMLayer.
When `safe_mode=True`, loading is disallowed because TFSMLayer
loads external SavedModels that may contain attacker-controlled
executable graph code. Defaults to `True`.
Returns:
A TFSMLayer instance.
"""
# Follow the same pattern as Lambda layer for safe_mode handling
effective_safe_mode = (
safe_mode
if safe_mode is not None
else serialization_lib.in_safe_mode()
)
if effective_safe_mode is not False:
raise ValueError(
"Requested the deserialization of a `TFSMLayer`, which "
"loads an external SavedModel. This carries a potential risk "
"of arbitrary code execution and thus it is disallowed by "
"default. If you trust the source of the artifact, you can "
"override this error by passing `safe_mode=False` to the "
"loading function, or calling "
"`keras.config.enable_unsafe_deserialization()."
)
return cls(**config)
View on GitHub (pinned to 7a34a03db6)
Solutions
- If you trust the artifact source, opt in once: keras.config.enable_unsafe_deserialization() before deserializing.
- Or pass safe_mode=False to the specific loading function (keras.saving.load_model(..., safe_mode=False)).
- For untrusted artifacts do not bypass; inspect the SavedModel (tf.saved_model.load) in a sandbox instead.
Example fix
# before cfg = layer.get_config() new_layer = keras.layers.deserialize(cfg) # -> ValueError # after import keras keras.config.enable_unsafe_deserialization() new_layer = keras.layers.deserialize(cfg)
Defensive patterns
Strategy: try-catch
Validate before calling
import keras
def can_deserialize_unsafe():
return getattr(keras.config, 'is_unsafe_deserialization_enabled', lambda: False)() Try / catch
try:
layer = keras.layers.deserialize(cfg)
except ValueError as e:
if 'unsafe_deserialization' in str(e) and trusted_source:
keras.config.enable_unsafe_deserialization()
layer = keras.layers.deserialize(cfg)
else:
raise Prevention
- Enable unsafe deserialization only in trusted local jobs; keep it off in services that accept uploads.
- Prefer exporting to .keras checkpoints that do not wrap external SavedModels.
- Never auto-bypass the guard for untrusted artifacts.
When it happens
Trigger: Round-tripping a TFSMLayer: layer.get_config() then keras.layers.deserialize(config) (e.g. in test_serialization); keras.models.load_model on a .keras file that embeds a TFSMLayer; loading third-party artifacts that wrap external SavedModels.
Common situations: Serializing a wrapper model that contains a TFSMLayer; CI tests that deserialize layers; loading third-party .keras artifacts from untrusted sources.
Related errors
- Requested the loading of a vocabulary file outside of the mo
- The TFSMLayer is only currently supported with the TensorFlo
- The endpoint '{call_endpoint}' is neither an attribute of th
- The endpoint '{call_training_endpoint}' is neither an attrib
- Unknown activation function '{activation}' cannot be seriali
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/05488166eedf8236.
Report an issue: GitHub.