pytorch - ✅(Solved) Fix [TensorSubclass] [torch.compile] Better Error message when tensor subclass metadata guard crashes with non-scalar tensors [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
pytorch/pytorch#178903Fetched 2026-04-08 01:57:05
View on GitHub
Comments
0
Participants
1
Timeline
37
Reactions
0
Participants
Timeline (top)
mentioned ×15subscribed ×15labeled ×5cross-referenced ×2

Error Message

AssertionError: Guard failed on the same frame it was created. This is a bug - please create an issue.Guard fail reason: 0/0: Boolean value of Tensor with more than one value is ambiguous

Fix Action

Fix / Workaround

@classmethod def torch_dispatch(cls, func, types, args=(), kwargs=None): def unwrap(t): return t._data if isinstance(t, WeightedTensor) else t

PR fix notes

PR #176044: [opaque object] Disallow creation of reference-type opaque objects under custom ops in torch.compile

Description (problem / solution / changelog)

Fixes https://github.com/pytorch/pytorch/issues/175968

Creation of reference-type opaque objects is not allowed under torch.compile. But it's unclear what to do when a user creates them under a custom op which is opaque to torch.compile. This PR chooses to raise on creation even under custom ops unless the user runs the creation under the unset_fake_temporarily context (an escape hatch for legit uses).

AI help used: Claude Opus 4.6

cc @voznesenskym @penguinwu @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @ipiszy @kadeng @muchulee8 @amjames @chauhang @aakhundov @coconutruben @jataylo @Lucaskabela @azahed98 @kshitij12345 @ptrblck @eqy @IvanYashchuk

Changed files

  • test/test_opaque_obj_v2.py (modified, +104/-2)
  • torch/_dynamo/decorators.py (modified, +5/-2)
  • torch/_higher_order_ops/invoke_leaf_function.py (modified, +9/-3)
  • torch/_opaque_base.py (modified, +21/-0)

PR #178910: [dynamo] Improve tensor subclass metadata guard error

Description (problem / solution / changelog)

Fixes #178903

cc @voznesenskym @penguinwu @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @kadeng @chauhang @amjames @Lucaskabela @jataylo @azahed98

Changed files

  • test/dynamo/test_subclasses.py (modified, +60/-0)
  • torch/_dynamo/guards.py (modified, +21/-2)

Code Example

"""
Repro: tensor subclass metadata guard crashes with non-scalar tensors.

The metadata guard (guards.py:2460) does:
    x.__tensor_flatten__()[1] == original_metadata

For dict comparison, Python does element-wise value comparison. When a value
is a multi-element tensor, `tensor == tensor` returns a multi-element bool
tensor. dict.__eq__ then tries bool() on it, which raises:
    "Boolean value of Tensor with more than one value is ambiguous"

This means __tensor_flatten__ metadata CANNOT contain non-scalar tensors,
though nothing documents or enforces this.
"""

import torch

class WeightedTensor(torch.Tensor):
    @staticmethod
    def __new__(cls, data, weights):
        return torch.Tensor._make_wrapper_subclass(
            cls,
            data.shape,
            dtype=data.dtype,
            device=data.device,
            requires_grad=data.requires_grad,
        )

    def __init__(self, data, weights):
        self._data = data
        self._weights = weights

    def __tensor_flatten__(self):
        # Putting a non-scalar tensor in metadata breaks the guard
        return ["_data"], {"weights": self._weights}

    @staticmethod
    def __tensor_unflatten__(inner_tensors, meta, outer_size, outer_stride):
        return WeightedTensor(inner_tensors["_data"], meta["weights"])

    @classmethod
    def __torch_dispatch__(cls, func, types, args=(), kwargs=None):
        def unwrap(t):
            return t._data if isinstance(t, WeightedTensor) else t

        out = func(
            *torch.utils._pytree.tree_map(unwrap, args),
            **torch.utils._pytree.tree_map(unwrap, kwargs or {}),
        )
        if isinstance(out, torch.Tensor) and not isinstance(out, WeightedTensor):
            return WeightedTensor(out, args[0]._weights)
        return out


def fn(x):
    return x * 2 + 1


# Works: scalar tensor in metadata
print("=== Scalar tensor in metadata ===")
x_ok = WeightedTensor(torch.randn(4), torch.tensor(1.0))
result = torch.compile(fn, backend="eager")(x_ok)


torch._dynamo.reset()

# Crashes: multi-element tensor in metadata
print("\n=== Multi-element tensor in metadata (5 elements) ===")
x_bad = WeightedTensor(torch.randn(4), torch.randn(5))
result = torch.compile(fn, backend="eager")(x_bad)

---

AssertionError: Guard failed on the same frame it was created. This is a bug - please create an issue.Guard fail reason: 0/0: Boolean value of Tensor with more than one value is ambiguous
RAW_BUFFERClick to expand / collapse

🐛 Describe the bug

"""
Repro: tensor subclass metadata guard crashes with non-scalar tensors.

The metadata guard (guards.py:2460) does:
    x.__tensor_flatten__()[1] == original_metadata

For dict comparison, Python does element-wise value comparison. When a value
is a multi-element tensor, `tensor == tensor` returns a multi-element bool
tensor. dict.__eq__ then tries bool() on it, which raises:
    "Boolean value of Tensor with more than one value is ambiguous"

This means __tensor_flatten__ metadata CANNOT contain non-scalar tensors,
though nothing documents or enforces this.
"""

import torch

class WeightedTensor(torch.Tensor):
    @staticmethod
    def __new__(cls, data, weights):
        return torch.Tensor._make_wrapper_subclass(
            cls,
            data.shape,
            dtype=data.dtype,
            device=data.device,
            requires_grad=data.requires_grad,
        )

    def __init__(self, data, weights):
        self._data = data
        self._weights = weights

    def __tensor_flatten__(self):
        # Putting a non-scalar tensor in metadata breaks the guard
        return ["_data"], {"weights": self._weights}

    @staticmethod
    def __tensor_unflatten__(inner_tensors, meta, outer_size, outer_stride):
        return WeightedTensor(inner_tensors["_data"], meta["weights"])

    @classmethod
    def __torch_dispatch__(cls, func, types, args=(), kwargs=None):
        def unwrap(t):
            return t._data if isinstance(t, WeightedTensor) else t

        out = func(
            *torch.utils._pytree.tree_map(unwrap, args),
            **torch.utils._pytree.tree_map(unwrap, kwargs or {}),
        )
        if isinstance(out, torch.Tensor) and not isinstance(out, WeightedTensor):
            return WeightedTensor(out, args[0]._weights)
        return out


def fn(x):
    return x * 2 + 1


# Works: scalar tensor in metadata
print("=== Scalar tensor in metadata ===")
x_ok = WeightedTensor(torch.randn(4), torch.tensor(1.0))
result = torch.compile(fn, backend="eager")(x_ok)


torch._dynamo.reset()

# Crashes: multi-element tensor in metadata
print("\n=== Multi-element tensor in metadata (5 elements) ===")
x_bad = WeightedTensor(torch.randn(4), torch.randn(5))
result = torch.compile(fn, backend="eager")(x_bad)

Fails with

AssertionError: Guard failed on the same frame it was created. This is a bug - please create an issue.Guard fail reason: 0/0: Boolean value of Tensor with more than one value is ambiguous

Versions

cf2fc89d70683363620a48963526c88ac12daffd

cc @chauhang @penguinwu @voznesenskym @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @kadeng @amjames @Lucaskabela @jataylo

extent analysis

TL;DR

The most likely fix is to ensure that the metadata in __tensor_flatten__ does not contain non-scalar tensors.

Guidance

  • Identify and modify the __tensor_flatten__ method in the WeightedTensor class to avoid returning non-scalar tensors in the metadata dictionary.
  • Verify that the __tensor_flatten__ method returns scalar tensors or other types that can be compared without raising a Boolean value of Tensor with more than one value is ambiguous error.
  • Consider adding input validation to ensure that the _weights attribute is a scalar tensor before passing it to __tensor_flatten__.
  • Test the modified WeightedTensor class with both scalar and non-scalar tensors to ensure that the fix works as expected.

Example

def __tensor_flatten__(self):
    # Ensure that metadata contains only scalar tensors
    return ["_data"], {"weights": self._weights.mean()}  # or another reduction method

Notes

The provided code snippet and error message suggest that the issue is related to the comparison of non-scalar tensors in the metadata. However, without more information about the desired behavior of the WeightedTensor class, it is difficult to provide a more specific solution.

Recommendation

Apply a workaround by modifying the __tensor_flatten__ method to ensure that it returns scalar tensors or other comparable types in the metadata dictionary. This will prevent the Boolean value of Tensor with more than one value is ambiguous error and allow the code to run without crashing.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING