TensorFlow
TensorShape
ValueError
debugging
machine learning

Tensorflow 2 throwing ValueError as_list is not defined on an unknown TensorShape

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The TensorFlow error saying as_list is not defined on an unknown TensorShape appears when code expects a fully known static shape but TensorFlow only has dynamic shape information at that point in graph execution. This is common in custom layers, tf.data pipelines, and tracing with tf.function. The fix is to use dynamic shape-safe operations and provide shape hints where possible.

Why This Error Happens

TensorFlow tracks shapes in two ways:

  • static shape metadata known at graph build time
  • dynamic runtime shape available only during execution

tensor.shape and tensor.shape.as_list() rely on static metadata. If dimension values are unknown, as_list() can fail.

A typical failing pattern:

python
1import tensorflow as tf
2
3@tf.function
4def bad_fn(x):
5    # may fail if shape is partially unknown during tracing
6    dims = x.shape.as_list()
7    return dims

Inside traced functions, static shape information can be incomplete, especially for batch dimension and dynamically sized inputs.

Prefer tf.shape for Dynamic Execution

When shape values are needed for computation, use tf.shape.

python
1import tensorflow as tf
2
3@tf.function
4def good_fn(x):
5    dyn_shape = tf.shape(x)
6    batch = dyn_shape[0]
7    width = dyn_shape[1]
8    return batch, width
9
10x = tf.ones((4, 8))
11print(good_fn(x))

tf.shape returns runtime tensor values and works even when static metadata is incomplete.

Use Shape Hints to Reduce Unknown Dimensions

Where possible, provide expected shape constraints to TensorFlow early.

python
1import tensorflow as tf
2
3inputs = tf.keras.Input(shape=(32,))
4x = tf.keras.layers.Dense(16)(inputs)
5model = tf.keras.Model(inputs, x)

For datasets, use output_signature or explicit tensor specs.

python
1import tensorflow as tf
2
3
4def gen():
5    for _ in range(3):
6        yield tf.ones((10,), dtype=tf.float32), tf.constant(1, dtype=tf.int32)
7
8
9ds = tf.data.Dataset.from_generator(
10    gen,
11    output_signature=(
12        tf.TensorSpec(shape=(10,), dtype=tf.float32),
13        tf.TensorSpec(shape=(), dtype=tf.int32),
14    ),
15)

These hints improve graph building and reduce shape ambiguity.

Custom Layer Pattern That Avoids as_list Issues

In custom Keras layers, avoid shape assumptions in call that require fully known static values.

python
1import tensorflow as tf
2
3class ScaleByFeatureCount(tf.keras.layers.Layer):
4    def call(self, x):
5        feature_count = tf.cast(tf.shape(x)[-1], tf.float32)
6        return x / tf.maximum(feature_count, 1.0)
7
8
9layer = ScaleByFeatureCount()
10print(layer(tf.ones((2, 5))))

If you need static shape for weight creation, do that in build, where input shape is provided.

python
1class MyDense(tf.keras.layers.Layer):
2    def build(self, input_shape):
3        in_dim = int(input_shape[-1])
4        self.w = self.add_weight(shape=(in_dim, 8), initializer="glorot_uniform")
5
6    def call(self, x):
7        return tf.matmul(x, self.w)

Mixed NumPy and TensorFlow Gotcha

Another trigger is mixing NumPy shape assumptions with TensorFlow symbolic tensors.

Unsafe pattern:

  • convert shape to Python list during graph tracing
  • use list values for tensor operations

Safer pattern:

  • keep shape operations in TensorFlow tensors using tf.shape
  • only convert to Python integers outside traced functions when guaranteed concrete

Debugging Workflow

When this error appears, isolate where as_list is called.

Practical steps:

  1. search for .shape.as_list() in custom code
  2. replace runtime-dependent uses with tf.shape
  3. add print(tensor.shape) before failing location to inspect static metadata
  4. add input signatures or tensor specs to reduce unknown dimensions
  5. test both eager mode and tf.function mode

This usually reveals whether failure is due to tracing context or missing input shape contracts.

Performance and Stability Notes

Using tf.shape for runtime computations is not just safer, it is often the correct graph-friendly approach. However, avoid excessive shape operations in inner loops when not needed. Keep shape logic minimal and consistent.

Also validate models with variable batch sizes, since unknown batch dimensions are a common source of shape-related errors.

Common Pitfalls

  • Calling as_list() inside traced code where static shape is partially unknown.
  • Assuming Keras input shape metadata is always fully defined at call time.
  • Building custom layers that mix static and dynamic dimensions incorrectly.
  • Defining tf.data pipelines without output_signature, causing shape ambiguity.
  • Converting symbolic dimensions to Python integers too early.

Summary

  • The error means TensorFlow lacks complete static shape information for as_list.
  • Use tf.shape for runtime-dependent dimension logic.
  • Provide input and dataset shape hints to improve graph inference.
  • Keep custom layer build and call responsibilities clear for shape handling.
  • Debug by finding static-shape assumptions and replacing them with dynamic-safe operations.

Course illustration
Course illustration

All Rights Reserved.