InterviewsVector

Fix: InvalidArgumentError — 'dtype' bfloat16 Not in List of Allowed Values

Quick answer

This error means the specific TensorFlow op you called has no bfloat16 kernel — not that bfloat16 is invalid (it is a real dtype). TensorFlow registers kernels per op and per dtype, and many ops only accept uint8/int32/int64/half/float/double. Fix it by casting to a supported dtype for that op: x = tf.cast(x, tf.float32), run the op, then cast back if downstream needs bfloat16. Casting bfloat16→float32 is lossless. Better yet, use tf.keras.mixed_precision.set_global_policy('mixed_bfloat16') so Keras handles dtype placement per layer.

Short answer: This error does not mean bfloat16 is invalid — it's a real dtype. It means the specific op you called has no bfloat16 kernel. Cast to float32 for that op with tf.cast, or use the mixed_bfloat16 policy so Keras places dtypes for you.

InvalidArgumentError: Value for attr 'dtype' of bfloat16 is not in the
list of allowed values: uint8, int32, int64, half, float, double

What's really happening

bfloat16 is a fully supported TensorFlow dtype. But TensorFlow doesn't implement every op for every dtype — kernels are registered per (operation, dtype) pair. When you pass a bfloat16 tensor to an op whose kernel list is uint8, int32, int64, half, float, double, there's simply no bfloat16 implementation to dispatch to, so you get InvalidArgumentError.

The "allowed values" in the message aren't TensorFlow's global dtype list — they're that op's registered kernels.

Fix: cast for the failing op

Cast to float32 before the op, then back afterward only if needed. Because bfloat16 shares float32's 8-bit exponent, widening is lossless:

import tensorflow as tf
 
x = tf.constant([1.0, 2.0, 3.0], dtype=tf.bfloat16)
 
# x = some_op(x)                  # raises InvalidArgumentError
x32 = tf.cast(x, tf.float32)
y = some_op(x32)                  # runs fine
y = tf.cast(y, tf.bfloat16)       # cast back if downstream expects bfloat16

Better: let mixed precision place dtypes

If you reached bfloat16 for training speed, don't hand-cast everywhere — use the mixed-precision policy. Keras runs most layers in bfloat16 while keeping numerically sensitive ops (softmax, loss, weight updates) in float32:

tf.keras.mixed_precision.set_global_policy("mixed_bfloat16")
# build/train your model normally

Make the final layer's output float32 explicitly for numerical safety:

outputs = tf.keras.layers.Dense(10)(x)
outputs = tf.keras.layers.Activation("softmax", dtype="float32")(outputs)

When bfloat16 is worth it

On TPUs and recent NVIDIA GPUs (Ampere+), bfloat16 roughly halves memory and speeds up training with almost no accuracy loss. On older hardware there's no speed benefit, so it just adds compatibility friction like this error.

Common traps

  • Reading the message as "bfloat16 is invalid" — it's op-specific, not global.
  • Casting to float16 insteadfloat16 has a smaller exponent than bfloat16 and can overflow; use float32.
  • Manual casts when you meant mixed precision — the policy API is cleaner and safer.

Sources

Key takeaways

  • bfloat16 IS a valid TensorFlow dtype — this error is about ONE op lacking a bfloat16 kernel.
  • Kernels are registered per (op, dtype); the allowed list in the message is exactly what that op supports.
  • Fix: tf.cast(x, tf.float32) before the failing op; cast back afterward only if needed.
  • bfloat16→float32 is lossless (same 8-bit exponent, fewer mantissa bits) — casting up never overflows.
  • Prefer mixed_bfloat16 policy over manual casts — Keras keeps sensitive ops (softmax/loss) in float32 for you.

Frequently asked questions

Why is bfloat16 'not in the list of allowed values' if TensorFlow supports it?

Because TensorFlow registers kernels per operation and per dtype. An op only accepts a dtype if a kernel was implemented and registered for that pair. Many ops — often older or less common ones — have no bfloat16 kernel, so passing one raises InvalidArgumentError even though the dtype itself is perfectly valid.

How do I fix the error?

Cast to a supported dtype before the failing op, usually float32: x = tf.cast(x, tf.float32). Run the op, then cast the result back to bfloat16 only if the rest of your pipeline needs it. bfloat16→float32 is lossless.

Will casting to float32 hurt accuracy?

No. bfloat16 has the same 8-bit exponent as float32 but only 7 mantissa bits, so widening to float32 loses nothing — it only adds precision. The cost is more memory and possibly slower execution for that one op.

Is there a cleaner fix than casting everywhere?

Yes — Keras mixed precision: tf.keras.mixed_precision.set_global_policy('mixed_bfloat16'). Keras then chooses dtypes per layer and keeps numerically sensitive operations like softmax and loss in float32 automatically, so you don't hand-place casts.

By Mohammad Wasi

Software Engineering Leader & Technical Author · Updated August 26, 2026


Related Posts