{"record":{"id":"4b953f18f37e7f06","repo":"keras-team/keras","slug":"unknown-activation-function-activation-cannot","errorCode":null,"errorMessage":"Unknown activation function '{activation}' cannot be serialized due to invalid function name. Make sure to use an activation name that matches the references defined in activations.py or use `@keras.saving.register_keras_serializable()`to register any custom activations. config={fn_config}","messagePattern":"Unknown activation function '(.+?)' cannot be serialized due to invalid function name\\. Make sure to use an activation name that matches the references defined in activations\\.py or use `@keras\\.saving\\.register_keras_serializable\\(\\)`to register any custom activations\\. config=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/activations/__init__.py","lineNumber":80,"sourceCode":"    hard_shrink,\n    linear,\n    mish,\n    log_softmax,\n    log_sigmoid,\n    sparsemax,\n}\n\nALL_OBJECTS_DICT = {fn.__name__: fn for fn in ALL_OBJECTS}\n# Additional aliases\nALL_OBJECTS_DICT[\"swish\"] = silu\nALL_OBJECTS_DICT[\"hard_swish\"] = hard_silu\n\n\n@keras_export(\"keras.activations.serialize\")\ndef serialize(activation):\n    fn_config = serialization_lib.serialize_keras_object(activation)\n    if \"config\" not in fn_config:\n        raise ValueError(\n            f\"Unknown activation function '{activation}' cannot be \"\n            \"serialized due to invalid function name. Make sure to use \"\n            \"an activation name that matches the references defined in \"\n            \"activations.py or use \"\n            \"`@keras.saving.register_keras_serializable()`\"\n            \"to register any custom activations. \"\n            f\"config={fn_config}\"\n        )\n    if not isinstance(activation, types.FunctionType):\n        # Case for additional custom activations represented by objects\n        return fn_config\n    if (\n        isinstance(fn_config[\"config\"], str)\n        and fn_config[\"config\"] not in globals()\n    ):\n        # Case for custom activation functions from external activations modules\n        fn_config[\"config\"] = object_registration.get_registered_name(\n            activation","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/activations/__init__.py#L62-L98","documentation":"Raised by keras.ops.image.extract_patches when the size argument is neither an int nor a tuple/list. extract_patches slices images into patches and must know the patch extent before touching tensors, so it validates size eagerly and rejects any other type with a TypeError naming the received type.","triggerScenarios":"Calling extract_patches(images, size=...) with a numpy array, a TensorShape, a string, None, or a generator as size; passing a config value loaded from YAML/JSON that arrived as something other than int, tuple or list.","commonSituations":"Dynamically built hyperparameter dicts (e.g. from a config file or CLI args) feeding size; porting code from torch.nn.Unfold or tf.image.extract_patches where size was a tensor; wrapping extract_patches in a layer whose build() passes through unvalidated user input.","solutions":["Pass an int or a tuple/list of 2 (2D images) or 3 (3D volumes) ints, e.g. size=3 or size=(3, 3)","If size comes from config or another framework, coerce it first: size = tuple(size) if isinstance(size, (list, tuple)) else int(size)","Guard inputs with a small validator before calling extract_patches when size is user-supplied"],"exampleFix":"before: patches = ops.image.extract_patches(img, size=np.array([3, 3])) -> TypeError; after: patches = ops.image.extract_patches(img, size=(3, 3))","handlingStrategy":"type-guard","validationCode":"def check_size(size):\n    if not isinstance(size, int) and not (isinstance(size, (tuple, list)) and 2 <= len(size) <= 3 and all(isinstance(v, int) for v in size)):\n        raise ValueError(\"size must be an int or a tuple/list of 2 or 3 ints\")\n    return size if isinstance(size, int) else tuple(size)","typeGuard":"def is_valid_patch_size(size) -> bool:\n    if isinstance(size, bool):\n        return False\n    if isinstance(size, int):\n        return True\n    return isinstance(size, (tuple, list)) and len(size) in (2, 3) and all(isinstance(v, int) and not isinstance(v, bool) for v in size)","tryCatchPattern":"try:\n    patches = keras.ops.image.extract_patches(img, size=size)\nexcept TypeError as e:\n    raise ValueError(f\"bad patch size from config: {size!r}\") from e","preventionTips":["Normalize size at the config boundary (CLI/YAML) into int or tuple","Never forward framework objects (TensorShape, ndarray) as size","Reuse the same validated size variable for extract and reconstruct"],"tags":["keras","argument-validation","typeerror","image-ops"],"backgroundTag":"invalid-argument-type","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}