TensorFlow "triggered tf.function retracing" warning (tested)
WARNING:tensorflow:5 out of the last 5 calls to <function> triggered tf.function retracing means each call built a new graph, usually because you pass Python numbers instead of tensors or a new shape each time. Measured below: 6 traces for 6 calls, down to 1 with tf.constant and 2 with reduce_retracing=True.
1. Reproduce
b1.py calls a @tf.function six times, passing a different Python int each time:
import os; os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
import tensorflow as tf
@tf.function
def scale(x, factor):
return x * factor
for i in range(6):
scale(tf.constant([1.0, 2.0]), i) # Python int: a new graph per value
print("traces:", scale.experimental_get_tracing_count())
WARNING:tensorflow:5 out of the last 5 calls to <function scale at 0x7f1b27e471a0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.
WARNING:tensorflow:6 out of the last 6 calls to <function scale at 0x7f1b27e471a0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.
traces: 6
It is a warning, not an exception: the results are correct, but every call built a new graph (6 traces for 6 calls), which is slower than plain eager code. Python values (ints, floats, strings, lists) are part of the trace signature, so each new value means a new trace.
2. Fix: pass tensors, and relax shapes
import os; os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
import tensorflow as tf
@tf.function
def scale(x, factor):
return x * factor
for i in range(6):
scale(tf.constant([1.0, 2.0]), tf.constant(float(i))) # tensor arg: one graph
print("traces:", scale.experimental_get_tracing_count())
@tf.function(reduce_retracing=True)
def total(x):
return tf.reduce_sum(x)
for n in range(1, 7):
total(tf.ones([n])) # new shape every call
print("reduce_retracing traces:", total.experimental_get_tracing_count())
traces: 1
reduce_retracing traces: 2
- Python scalars: wrap them in
tf.constant(...); the same function now traces once for all six calls. - Changing shapes:
@tf.function(reduce_retracing=True)traced twice for six different lengths, then reused a generalized shape. An explicitinput_signature=[tf.TensorSpec([None], tf.float32)]pins it to one trace. - Function defined in a loop: each new
tf.functionobject traces from scratch; define it once, outside the loop (cause (1) in the warning).
Count traces yourself with fn.experimental_get_tracing_count(), as above.
Related: TensorFlow Keras errors after Keras 3, pip install tensorflow: no matching distribution found.
Frequently asked questions
What does triggered tf.function retracing mean?
The tf.function built a new graph on (almost) every call. It is a performance warning; results are still correct.
How do I stop tf.function retracing?
Pass tensors instead of Python scalars, define the function once outside loops, and use reduce_retracing=True or an input_signature when shapes change.
How can I count how often a tf.function traced?
Call fn.experimental_get_tracing_count() on the decorated function.
Written with AI assistance. Measured on 2026-10-24 with tensorflow-cpu 2.21.0 and Python 3.13.5 on Linux. The scripts ran verbatim and the output was pasted unedited (TensorFlow startup log lines filtered). PlainTables is our extension; TensorFlow is free.