TypeError: Exception encountered when calling layer "custom_crop_layer_2" " f"(type CustomCropLayer).
@pzy2000,
The error message "unsupported operand type(s) for -: 'NoneType' and 'int'" suggests that a computation is attempted between NoneType (which indicates a missing value) and an integer. Also I tried to execute the mentioned code and it was executed with a different error. Kindly find the gist of it [here](https://colab.research.google.com/gist/tilakrayal/054c94df5403bc8335ceabc6836247db/untitled1766.ipynb) and share the required dependencies. Thank you! > @pzy2000, The error message "unsupported operand type(s) for -: 'NoneType' and 'int'" suggests that a computation is attempted between NoneType (which indicates a missing value) and an integer. Also I tried to execute the mentioned code and it was executed with a different error. Kindly find the gist of it [here](https://colab.research.google.com/gist/tilakrayal/054c94df5403bc8335ceabc6836247db/untitled1766.ipynb) and share the required dependencies. Thank you!

sorry, I forgot to share the model file, it is here:
https://drive.google.com/file/d/14Lph3YKjXJVy3huIFCYoQJ4DrqgKs5tf/view?usp=sharing @pzy2000,
I tried to execute the mentioned code using the .h5 file provided and execute with the different error. AFAIK I tried to execute the model with tensorflow v2.16, and tried to run the inference for the .h5 model which was on tensorflow older versions and it was failing due to this extra layer which was not present in before versions. Kindly find the gist of it [here](https://colab.research.google.com/gist/tilakrayal/5b7be7acfb8b8adfc48c43fa2b8fbebc/untitled1788.ipynb). 

And also this issue is related to Keras, Could you please reach out to keras-team/keras repo for the quick response. Thank you! This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. This issue was closed because it has been inactive for 7 days since being marked as stale. Please reopen if you'd like to work on this further. Are you satisfied with the resolution of your issue?
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/63788">Yes</a>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/63788">No</a>

### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

Yes

### Source

binary

### TensorFlow version

tf 2.10.0

### Custom code

Yes

### OS platform and distribution

Linux Ubuntu 20.04.4

### Mobile device

_No response_

### Python version

3.7.6

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

12.2

### GPU model and memory

_No response_

### Current behavior?

Expect: 
successfully saved to tf format ckpt.
Now:
![image](https://github.com/tensorflow/tensorflow/assets/77827720/3613285c-3966-403e-97a2-4a5649f34ca7)

Traceback (most recent call last):
  File "issue_tf2onnx_001.py", line 207, in <module>
    model.save(f'tmp/lenet5_sb', save_format='tf')
  File "/opt/conda/envs/tf2onnx/lib/python3.7/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/opt/conda/envs/tf2onnx/lib/python3.7/contextlib.py", line 119, in __exit__
    next(self.gen)
  File "issue_tf2onnx_001.py", line 77, in call
    indices.append(slice(0 + crop[0], shape - crop[1]))
TypeError: Exception encountered when calling layer "custom_crop_layer_2" "                 f"(type CustomCropLayer).

unsupported operand type(s) for -: 'NoneType' and 'int'

Call arguments received by layer "custom_crop_layer_2" "                 f"(type CustomCropLayer):
  • args=('tf.Tensor(shape=(None, None, None, 32), dtype=float32)',)
  • kwargs={'training': 'False'}


### Standalone code to reproduce the issue

```shell
import keras
import tensorflow as tf


class CustomCastLayer(keras.layers.Layer):
    def __init__(self, target_dtype, **kwargs):
        self.target_dtype = target_dtype
        super().__init__(**kwargs)

    def build(self, input_shape):
        """
        Do Nothing
        """
        super().build(input_shape)

    def call(self, inputs, **kwargs):
        output = tf.cast(inputs, self.target_dtype)
        return output

    def get_config(self):
        config = super().get_config()
        config.update({"target_dtype": self.target_dtype})
        return config

    def compute_output_shape(self, input_shape):
        """
        Do Nothing
        """
        return input_shape


class CustomPadLayer(keras.layers.Layer):
    def __init__(self, padding=[[0, 0]], constant_values=0, **kwargs):
        self.padding = padding  # add [0,0] to padding so we will not change the shape of batch dimension
        self.constant_values = constant_values
        super().__init__(**kwargs)

    def build(self, input_shape):
        super().build(input_shape)

    def call(self, inputs, **kwargs):
        output = tf.pad(inputs, paddings=tf.constant([[0, 0]] + self.padding), mode="CONSTANT",
                        constant_values=self.constant_values)
        return output

    def get_config(self):
        config = super().get_config()
        config.update({"padding": self.padding, "constant_values": self.constant_values})
        return config

    def compute_output_shape(self, input_shape):
        """
        Formula to calculate the output shape
        Suppose the input_shape is (None, N, W, C), the `paddings` is [[a, b], [c, d]].
        The output_shape is (None, N+a+b, W+c+d, C).
        """
        input_shape_list = list(input_shape)
        padding = [[0, 0]] + self.padding
        assert len(input_shape_list) == len(padding)  # Two dimensions should match.
        output_shape = [None]
        for i, pad in zip(input_shape_list[1:], padding[1:]):
            output_shape.append(i + pad[0] + pad[1])
        return tuple(output_shape)


class CustomCropLayer(keras.layers.Layer):
    def __init__(self, cropping, **kwargs):
        self.cropping = cropping
        super().__init__(**kwargs)

    def build(self, input_shape):
        super().build(input_shape)

    def call(self, inputs, **kwargs):
        input_shape = inputs.shape.as_list()
        indices = [slice(None)]
        cropping = [[0, 0]] + self.cropping  # add [0,0] to padding so we will not change the shape of batch dimension
        for shape, crop in zip(input_shape[1:], cropping[1:]):
            indices.append(slice(0 + crop[0], shape - crop[1]))
        return inputs[indices]

    def get_config(self):
        config = super().get_config()
        config.update({"cropping": self.cropping})
        return config

    def compute_output_shape(self, input_shape):
        """
        Formula to calculate the output shape
        Suppose the input_shape is (None, N, W, C), the `cropping` is [[a, b], [c, d]].
        The output_shape is (None, N-a-b, W-c-d, C).
        """
        input_shape_list = list(input_shape)
        cropping = [[0, 0]] + self.cropping
        assert len(input_shape_list) == len(cropping)  # Two dimensions should match.
        output_shape = [None]
        for i, crop in zip(input_shape[1:], cropping[1:]):
            output_shape.append(i - crop[0] - crop[1])
        return tuple(output_shape)


class CustomExpandLayer(keras.layers.Layer):
    def __init__(self, axis=1, **kwargs):
        self.axis = axis
        super().__init__(**kwargs)

    def build(self, input_shape):
        super().build(input_shape)

    def call(self, inputs, **kwargs):
        return tf.expand_dims(inputs, self.axis)

    def get_config(self):
        config = super().get_config()
        config.update({"axis": self.axis})
        return config

    def compute_output_shape(self, input_shape):
        """
        Formula to calculate the output shape
        Suppose the input_shape is [None, N, W, C]:
        axis=0:
            output_shape: [1, None, N, W, C]
        axis=1 (default):
            output_shape: [None, 1, N, W, C]
        axis=2:
            output_shape: [None, N, 1, W, C]
        axis=3:
            output_shape: [None, N, W, 1, C]
        axis=4:
            output_shape: [None, N, W, C, 1]
        axis=5:
            raise Exception
        """
        input_shape_list = list(input_shape)
        if self.axis > len(input_shape_list):
            raise ValueError(f"axis {self.axis} should be smaller than input_shape + 1: {len(input_shape_list) + 1}")
        output_shape = input_shape_list[0:self.axis] + [1] + input_shape_list[self.axis:]
        return tuple(output_shape)  # we should use tuple!!! not list !!!


class CustomDropDimLayer(keras.layers.Layer):
    def __init__(self, axis=1, **kwargs):
        self.axis = axis
        super().__init__(**kwargs)

    def build(self, input_shape):
        super().build(input_shape)

    def call(self, inputs, **kwargs):
        """
        Something magic to automatically generate indices for array slicing.
        To determine a specific axis, we can use slice(None) to replace `:`
        """
        dim = len(inputs.shape)
        if self.axis > dim - 1 or self.axis < 1:
            raise ValueError(f"axis: {self.axis} should be within the range: [1, {dim - 1}] for {dim}D tensor")
        indices = [slice(None) for i in range(dim)]
        indices[self.axis] = 0
        return inputs[indices]

    def get_config(self):
        config = super().get_config()
        config.update({"axis": self.axis})
        return config

    def compute_output_shape(self, input_shape):
        """
        Formula to calculate the output shape
        Suppose the input_shape is [None, N, W, C]:
        axis=0:  # Although it is feasible, we don't allow this to happen
            Raise Exception
        axis=1 (default):
            output_shape: [None, W, C]
        axis=2:
            output_shape: [None, N, C]
        axis=3:
            output_shape: [None, N, W]
        axis=4:
            Raise Exception
        """
        input_shape_list = list(input_shape)
        output_shape = input_shape_list[0:self.axis] + input_shape_list[self.axis + 1:]
        return tuple(output_shape)


def custom_objects(mode="custom"):
    def no_activation(x):
        return x

    def leakyrelu(x):
        import keras.backend as K
        return K.relu(x, alpha=0.01)

    # objects = {}
    objects = {'no_activation': no_activation, 'leakyrelu': leakyrelu}
    if mode == "custom":
        objects['CustomPadLayer'] = CustomPadLayer
        objects['CustomCropLayer'] = CustomCropLayer
        objects['CustomDropDimLayer'] = CustomDropDimLayer
        objects['CustomExpandLayer'] = CustomExpandLayer
        objects['CustomCastLayer'] = CustomCastLayer

    return objects


model_path = "/data1/pzy/MUTANTS/LEMON/lenet5_fashion/lenet5-fashion-mnist_origin-NLAll30-LMerg38-Edge63-NLAll90-92/lenet5-fashion-mnist_origin-NLAll30-LMerg38-Edge63-NLAll90.h5"
model = tf.keras.models.load_model(model_path, custom_objects=custom_objects())
# model = tf.keras.models.load_model(model_path,)
model.save(f'tmp/lenet5_sb', save_format='tf')
```


### Relevant log output

```shell
Traceback (most recent call last):
  File "issue_tf2onnx_001.py", line 207, in <module>
    model.save(f'tmp/lenet5_sb', save_format='tf')
  File "/opt/conda/envs/tf2onnx/lib/python3.7/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/opt/conda/envs/tf2onnx/lib/python3.7/contextlib.py", line 119, in __exit__
    next(self.gen)
  File "issue_tf2onnx_001.py", line 77, in call
    indices.append(slice(0 + crop[0], shape - crop[1]))
TypeError: Exception encountered when calling layer "custom_crop_layer_2" "                 f"(type CustomCropLayer).

unsupported operand type(s) for -: 'NoneType' and 'int'

Call arguments received by layer "custom_crop_layer_2" "                 f"(type CustomCropLayer):
  • args=('tf.Tensor(shape=(None, None, None, 32), dtype=float32)',)
  • kwargs={'training': 'False'}
```
