TensorFlow
TypeError
DataType
uint8
float32

TensorFlow TypeError Value passed to parameter input has DataType uint8 not in list of allowed values float16, float32

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

This TensorFlow error means you passed an integer tensor (typically image pixel values stored as uint8, 0-255) to an operation that requires floating-point input (float16 or float32). The fix is to cast your tensor before the operation: tf.cast(tensor, tf.float32). For images, also normalize to the 0-1 range by dividing by 255.0. This error commonly appears when loading images, building preprocessing pipelines, or feeding raw data into model layers.

The Error

python
1import tensorflow as tf
2
3# Load an image — returns uint8 by default
4image = tf.io.read_file("photo.jpg")
5image = tf.image.decode_jpeg(image)  # Shape: (H, W, 3), dtype: uint8
6
7# This fails — Conv2D expects float input
8model = tf.keras.Sequential([
9    tf.keras.layers.Conv2D(32, 3, activation="relu")
10])
11output = model(tf.expand_dims(image, 0))
12# TypeError: Value passed to parameter 'input' has DataType uint8
13# not in list of allowed values: float16, float32

Fix: Cast to float32

python
1import tensorflow as tf
2
3image = tf.io.read_file("photo.jpg")
4image = tf.image.decode_jpeg(image)  # uint8, values 0-255
5
6# Cast and normalize
7image = tf.cast(image, tf.float32) / 255.0  # float32, values 0.0-1.0
8
9# Now it works
10output = model(tf.expand_dims(image, 0))

Common Scenarios and Fixes

Image Loading Pipeline

python
1def load_and_preprocess(path, label):
2    image = tf.io.read_file(path)
3    image = tf.image.decode_jpeg(image, channels=3)
4    image = tf.image.resize(image, [224, 224])  # resize outputs float32
5    image = image / 255.0  # normalize
6    return image, label
7
8# tf.data pipeline
9dataset = tf.data.Dataset.from_tensor_slices((file_paths, labels))
10dataset = dataset.map(load_and_preprocess)

Note: tf.image.resize() automatically casts to float32, but other operations like tf.image.random_flip_left_right() preserve the input dtype.

Using tf.data with numpy Arrays

python
1import numpy as np
2
3# numpy arrays default to uint8 for images
4images = np.random.randint(0, 256, (100, 28, 28, 1), dtype=np.uint8)
5labels = np.random.randint(0, 10, (100,))
6
7# WRONG: feeding uint8 directly
8dataset = tf.data.Dataset.from_tensor_slices((images, labels))
9
10# FIX: cast in the pipeline
11dataset = dataset.map(lambda x, y: (tf.cast(x, tf.float32) / 255.0, y))
12
13# Or cast before creating the dataset
14images_float = images.astype(np.float32) / 255.0
15dataset = tf.data.Dataset.from_tensor_slices((images_float, labels))

Keras ImageDataGenerator

python
1from tensorflow.keras.preprocessing.image import ImageDataGenerator
2
3# ImageDataGenerator handles casting via rescale
4datagen = ImageDataGenerator(rescale=1.0/255.0)
5
6train_generator = datagen.flow_from_directory(
7    "data/train",
8    target_size=(224, 224),
9    batch_size=32,
10)
11# Output is already float32 in range [0, 1]

tf.keras.utils.image_dataset_from_directory

python
1# Modern API — returns uint8 by default
2dataset = tf.keras.utils.image_dataset_from_directory(
3    "data/train",
4    image_size=(224, 224),
5    batch_size=32,
6)
7
8# Add normalization as a preprocessing layer
9model = tf.keras.Sequential([
10    tf.keras.layers.Rescaling(1.0/255.0),  # Handles the conversion
11    tf.keras.layers.Conv2D(32, 3, activation="relu"),
12    # ...
13])

Mathematical Operations

python
1# WRONG: uint8 tensors in math operations
2a = tf.constant([100, 200, 250], dtype=tf.uint8)
3b = tf.constant([50, 100, 150], dtype=tf.uint8)
4
5# Subtraction with uint8 wraps around (underflow)
6result = a - b  # [50, 100, 100] — 250-150=100 is fine, but negatives would wrap
7
8# FIX: cast first
9a_float = tf.cast(a, tf.float32)
10b_float = tf.cast(b, tf.float32)
11result = a_float - b_float  # [50.0, 100.0, 100.0]

Using Preprocessing Layers

The cleanest approach for Keras models — include normalization in the model:

python
1model = tf.keras.Sequential([
2    # Input preprocessing
3    tf.keras.layers.Rescaling(1.0/255.0, input_shape=(224, 224, 3)),
4
5    # Model layers
6    tf.keras.layers.Conv2D(32, 3, activation="relu"),
7    tf.keras.layers.MaxPooling2D(),
8    tf.keras.layers.Flatten(),
9    tf.keras.layers.Dense(10, activation="softmax"),
10])
11
12# Feed uint8 images directly — Rescaling handles the conversion
13model.predict(uint8_images)  # Works without manual casting

Checking and Converting dtypes

python
1tensor = tf.constant([1, 2, 3])
2print(tensor.dtype)  # tf.int32
3
4# Check dtype
5if tensor.dtype != tf.float32:
6    tensor = tf.cast(tensor, tf.float32)
7
8# For numpy arrays
9import numpy as np
10arr = np.array([1, 2, 3], dtype=np.uint8)
11print(arr.dtype)  # uint8
12arr_float = arr.astype(np.float32) / 255.0

Common Pitfalls

  • Casting to float32 without normalizing: tf.cast(image, tf.float32) converts pixel values to floats but keeps them in the 0-255 range. Most models expect input in 0-1 (divide by 255.0) or -1 to 1 (divide by 127.5, subtract 1). Unnormalized inputs cause poor training and NaN losses.
  • Assuming tf.image.resize() preserves uint8: tf.image.resize() casts to float32 internally for interpolation. This can be surprising — the output is float32 even if the input was uint8, but the values are still in the 0-255 range unless you normalize.
  • Using integer division instead of float division: In Python 3, image / 255 works correctly (float division). But image // 255 performs integer division, converting all values to 0 or 1. Always use / 255.0 to be explicit.
  • Applying data augmentation before casting: Some tf.image functions (like random_brightness) require float input, while others (like random_flip_left_right) accept uint8. Cast to float32 early in the preprocessing pipeline to avoid errors.
  • Double normalization: If using Rescaling(1.0/255.0) in the model and also dividing by 255 in the data pipeline, images are normalized twice (values become 0 to 1/255). The model receives near-zero inputs, leading to very poor performance without obvious errors.

Summary

  • Cast uint8 tensors to float32 with tf.cast(tensor, tf.float32) / 255.0
  • Use tf.keras.layers.Rescaling(1.0/255.0) as a model layer for automatic handling
  • ImageDataGenerator(rescale=1.0/255.0) handles conversion in legacy pipelines
  • Normalize images to 0-1 or -1 to 1 range — do not feed raw 0-255 float values to models
  • Cast early in your preprocessing pipeline before applying mathematical operations

Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Basis Lab
No course covers this one yet

Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.

Build my course
ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design