GB0150

Graph-Break Type

Short name describing what triggered the graph break

Unsupported hasattr call

Context

Values or code snippet captured at the break point

call_obj_hasattr {self} {name}

Explanation

Explanation of why the graph break was triggered

Dynamo does not know how to trace the function {self.debug_repr()}

Hints

Hints on how to resolve the graph break

Additional Information

This graph break happens when you call hasattr(obj, name) on a value whose type Dynamo cannot inspect for attributes. This commonly happens with lazy builtin iterators (map, zip, filter), slice, super() objects, and similar types. A frequent source is duck-typing helpers that branch on hasattr(...) and get handed one of these objects.

Example code that causes the graph break is:

import torch


def collate(values):
    # Duck-typing: branch on whether we can cheaply get a length.
    if hasattr(values, "__len__"):
        return torch.zeros(len(values))
    return torch.zeros(1)


@torch.compile(fullgraph=True)
def fn(x):
    # `map(...)` is a lazy iterator that Dynamo cannot inspect, so the
    # `hasattr` call inside `collate` breaks the graph.
    doubled = map(lambda v: v * 2, [1.0, 2.0, 3.0])
    return x + collate(doubled).sum()


fn(torch.randn(3))

The cleanest workaround is to convert the lazy iterator into a type Dynamo understands (e.g. a list) before calling hasattr on it. hasattr is supported on list, tuple, dict, tensors, modules, and user-defined objects:

import torch


def collate(values):
    if hasattr(values, "__len__"):
        return torch.zeros(len(values))
    return torch.zeros(1)


@torch.compile(fullgraph=True)
def fn(x):
    # A list supports `hasattr`/`len`, so `torch.compile` handles it without a break.
    doubled = list(map(lambda v: v * 2, [1.0, 2.0, 3.0]))
    return x + collate(doubled).sum()


fn(torch.randn(3))

Alternatively, if the hasattr check is only deciding control flow that is fixed each time the function runs, compute it outside the compiled region and pass the result in, so Dynamo never has to inspect the unsupported object.

Click here to add Additional Info

Back to Registry