[dynamo] `str(KeyError(...))` inside a traced region omits the quotes CPython adds (`"'k'"` in eager, `'k'` compiled)
Describe the bug
Summary. str() of a caught KeyError inside a fully traced compiled function does not match eager: CPython's KeyError.__str__ returns the repr of the key ("'k'"), while Dynamo returns the plain message ('k'), including in f-strings and for a KeyError raised by a dict lookup; repr(e), e.args, other exception types, and code after a graph break behave like eager (torch 2.14.0 and nightly). A user who matches on str(e) or logs it sees different text once the function is compiled. Because the exception variable dispatches __str__ to the base implementation rather than to KeyError.__str__, the outcome is decided by whether the try block was traced or resumed.
CPython's KeyError.__str__ returns the repr of a single argument (str(KeyError("k")) == "'k'"). Inside a torch.compiled function that Dynamo traces fully, str(e) for a caught KeyError returns the plain message instead:
import torch
def f(x):
try:
raise KeyError("k")
except KeyError as e:
return x, str(e), f"key error: {e}"
def g(x):
d = {}
try:
d["missing"]
except KeyError as e:
return x, str(e)
x = torch.zeros(1)
print(f(x)[1:]) # ("'k'", "key error: 'k'")
print(torch.compile(f, backend="eager", fullgraph=True)(x)[1:]) # ('k', 'key error: k')
print(g(x)[1], torch.compile(g, backend="eager", fullgraph=True)(x)[1]) # 'missing' 'missing' -> "'missing'" vs 'missing'
Output (torch 2.14.0+cpu and 2.15.0.dev20260911+cpu):
("'k'", "key error: 'k'")
('k', 'key error: k')
'missing' missing
repr(e) and e.args are not affected. Other exception types (ValueError("v") → 'v') agree because their __str__ is the base one. If the try block sits after a graph break (e.g. torch._dynamo.graph_break() right before it), the real exception object is used and the result matches eager — which is how the differential test first noticed it: the same program gave the right string in the resumed part and the wrong one in the traced part.
Expected: str(e) identical to eager (Dynamo's exception variable should dispatch __str__ to the concrete exception class, KeyError.__str__, not BaseException.__str__).
Error logs
No error; string differs.
Versions
(torch 2.14.0+cpu, Windows 11, Python 3.14; same on the 2026-09-11 nightly wheel, and on Linux with Python 3.11: torch 2.14.0+cpu and 2.15.0.dev20260912+cpu.)
cc @chauhang @penguinwu @voznesenskym @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @kadeng @amjames @jataylo @azahed98
Source: pytorch/pytorch