huggingface / huggingface/diffusers

`register_to_config` mislabels positional `__init__` args as `_use_default_values`, so `from_config` round trips silently revert them to defaults

Open Beginner friendly
#14,460 3 comments 0 reactions 0 assignees View on GitHub
bug models
Dominant language
Python
Stars
34.5k
Forks
7.3k
Avg merge
3d 3h
Merged PRs (30d)
91

Description

### Describe the bug

`@register_to_config` computes `_use_default_values` as `set(new_kwargs) - set(init_kwargs)`, but `init_kwargs` only contains *keyword* arguments (`src/diffusers/configuration_utils.py:725-726`). Any constructor argument passed **positionally** is mislabeled as "used default value", and `extract_init_dict` then strips it on every `from_config` round trip (`configuration_utils.py:500-501`).

- Expected: per the comment at `configuration_utils.py:499` ("Skip keys that were *not present* in the original config, so default `__init__` values were used") and the design intent in https://github.com/huggingface/diffusers/pull/3929#issuecomment-1618919655, `_use_default_values` should only contain parameters the caller did not provide — positional and keyword calls should round-trip identically.
- Actual: the config *displays* the explicitly-set value, but `from_config(obj.config)` (the documented scheduler-swap pattern) silently reverts it to the class default. Affects every `ConfigMixin` subclass.

I'd be happy to open a PR: exclude positionally-bound parameter names from the `_use_default_values` computation in `inner_init` (a two-line change), plus a regression test in `tests/others/test_config.py` — once a maintainer acks, per the AI-assisted contributions guidelines.

### Reproduction

```python
from diffusers import DDIMScheduler, EulerDiscreteScheduler

s = DDIMScheduler(500) # positional, explicit non-default value
print(s.config.num_train_timesteps) # 500
print("num_train_timesteps" in s.config["_use_default_values"]) # True <-- mislabeled

print(DDIMScheduler.from_config(s.config).config.num_train_timesteps) # 1000, expected 500
print(EulerDiscreteScheduler.from_config(s.config).config.num_train_timesteps) # 1000, expected 500

k = DDIMScheduler(num_train_timesteps=500) # keyword control group
print(DDIMScheduler.from_config(k.config).config.num_train_timesteps) # 500, correct
```

### Logs

```shell
(no traceback — the failure mode is a silently wrong value)
```

### System Info

- 🤗 Diffusers version: 0.40.0.dev0 (`main` @ 614ae4b)
- Platform: macOS-26.5.2-arm64-arm-64bit-Mach-O
- Python version: 3.13.3
- PyTorch version (GPU?): 2.13.0 (False)
- Huggingface_hub version: 1.27.0
- Transformers version: 5.15.0
- Safetensors version: 0.8.0
- Using GPU in script?: No

### Who can help?

_No response_

---

Disclosure: this report was prepared with AI assistance; I reproduced the issue locally and reviewed every claim myself.

Contributor guide

Open the contributing guide

Research direction

Start in src/diffusers/configuration_utils.py around inner_init at lines 725-726 and inspect extract_init_dict around lines 499-501. Run the reproduction and add the regression coverage in tests/others/test_config.py. Done means positional and keyword constructor arguments both preserve their explicit values through from_config round trips.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
developer-experience
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.