Skip to content

fix(modeling_utils): rename shadowed tuple loop var in get_parameter_dtype (#13789)#13791

Open
Anai-Guo wants to merge 1 commit into
huggingface:mainfrom
Anai-Guo:fix/get-parameter-dtype-tuple-shadow
Open

fix(modeling_utils): rename shadowed tuple loop var in get_parameter_dtype (#13789)#13791
Anai-Guo wants to merge 1 commit into
huggingface:mainfrom
Anai-Guo:fix/get-parameter-dtype-tuple-shadow

Conversation

@Anai-Guo
Copy link
Copy Markdown

What

Fixes #13789.

Inside get_parameter_dtype (src/diffusers/models/modeling_utils.py), the
inner find_tensor_attributes fallback used for nn.DataParallel
compatibility is annotated with list[tuple[str, Tensor]]. The enclosing
function also did:

for tuple in gen:
    last_tuple = tuple
    if tuple[1].is_floating_point():
        return tuple[1].dtype

Assigning to tuple anywhere in get_parameter_dtype makes it a function-
local for the entire scope. When execution reaches the DataParallel fallback
before the for loop has ever bound tuple — which is exactly what happens
under nn.DataParallel where the replicated module on the non-master device
has empty named_parameters() / named_buffers() — the inner function
annotation evaluates tuple[str, Tensor] and raises:

UnboundLocalError: cannot access local variable tuple where it is not associated with a value

This breaks UNet2DModel(...).cuda(); torch.nn.DataParallel(model, ...)
forward, because unet_2d.UNet2DModel.forward does t_emb.to(dtype=self.dtype).

Fix

Rename the loop variable to named_tensor so the builtin tuple is no
longer shadowed. get_parameter_device already uses a distinct name
(first_tuple) and is not affected.

Minimal diff in get_parameter_dtype:

     gen = parameter._named_members(get_members_fn=find_tensor_attributes)
     last_tuple = None
-    for tuple in gen:
-        last_tuple = tuple
-        if tuple[1].is_floating_point():
-            return tuple[1].dtype
+    for named_tensor in gen:
+        last_tuple = named_tensor
+        if named_tensor[1].is_floating_point():
+            return named_tensor[1].dtype

Repro

The repro from #13789 (two-GPU nn.DataParallel(UNet2DModel(...))) raises
UnboundLocalError on main and runs to completion with this patch.


AI-assisted, human reviewed.

…r_dtype (huggingface#13789)

Inside `get_parameter_dtype`, the inner `find_tensor_attributes` fallback
(used for nn.DataParallel compatibility) is annotated with
`list[tuple[str, Tensor]]`. The enclosing function also did
`for tuple in gen:`, which makes `tuple` a local of
`get_parameter_dtype` for the entire function scope. When the dtype path
falls through to the DataParallel fallback (e.g. a replicated module on
non-master devices has empty named_parameters/buffers), the inner
function annotation evaluates `tuple[str, Tensor]` and raises
`UnboundLocalError: cannot access local variable 'tuple'` because the
loop has not yet executed.

Rename the loop variable to `named_tensor` so the builtin is no longer
shadowed. `get_parameter_device` already uses a distinct name
(`first_tuple`) and is unaffected.
@github-actions github-actions Bot added size/S PR with diff < 50 LOC models fixes-issue and removed size/S PR with diff < 50 LOC labels May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UNet2DModel dtype property fails under nn.DataParallel with UnboundLocalError in get_parameter_dtype

1 participant