fix: avoid leading separator in user_agent when no caller-supplied agent is provided#510
Merged
danieldk merged 2 commits intoMay 1, 2026
Conversation
_get_hf_api() built user_agent_str = "" then did
user_agent_str += "; kernels/...", producing a leading "; ". When the
resulting string was forwarded to HfApi(...), huggingface_hub joined
its own fields with another "; ", producing an empty token in the
final User-Agent. After dedup, this left a trailing "; " in the
header, which strict HTTP clients (httpx >= 0.25) reject with
LocalProtocolError: Illegal header value.
This breaks any code path that triggers _get_hf_api() without
supplying a user_agent — most notably _get_available_versions(),
which transformers hits when resolving finegrained-fp8 / deep-gemm
kernel versions for FP8 models.
Build the system info as a separate sys_info string with no leading
separator, then join it onto any caller-supplied user_agent with a
single "; " only when the caller-supplied part is non-empty. Adds
a regression test in test_user_agent.py covering None, "", and {}
inputs.
danieldk
reviewed
Apr 29, 2026
Comment on lines
+638
to
+657
| backend = _select_backend(None).variant_str | ||
| user_agent_str += ( | ||
| f"; kernels/{__version__}; python/{python}; backend/{backend}; platform/{_platform()}; file_type/kernel" | ||
| sys_info = ( | ||
| f"kernels/{__version__}; python/{python}; backend/{backend}; platform/{_platform()}; file_type/kernel" | ||
| ) | ||
|
|
||
| if has_torch: | ||
| import torch | ||
|
|
||
| user_agent_str += f"; torch/{torch.__version__}" | ||
| sys_info += f"; torch/{torch.__version__}" | ||
| if has_tvm_ffi: | ||
| import tvm_ffi | ||
|
|
||
| user_agent_str += f"; tvm-ffi/{tvm_ffi.__version__}" | ||
| sys_info += f"; tvm-ffi/{tvm_ffi.__version__}" | ||
|
|
||
| # Add glibc version if available | ||
| glibc = glibc_version() | ||
| if glibc is not None: | ||
| user_agent_str += f"; glibc/{glibc}" | ||
| sys_info += f"; glibc/{glibc}" | ||
|
|
||
| user_agent_str = f"{user_agent_str}; {sys_info}" if user_agent_str else sys_info |
Member
There was a problem hiding this comment.
I think rather than juggling with a lot of strings, it might be better to push everything to a list and then '; '.join it?
Contributor
Author
There was a problem hiding this comment.
Good call — refactored in 3208d97 to build a list of parts and '; '.join at the end. Behavior is unchanged, the test still passes, just less branchy.
Address review feedback: replace the user_agent_str string-juggling with a single list of parts that gets joined at the end. Behavior is identical to the previous commit (existing test_user_agent_no_leading_or_empty_segment still passes), the code is just less branchy.
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_get_hf_api()inkernels/src/kernels/utils.pyproduces a malformed user-agent when nouser_agentargument is passed. The emptyuser_agent_stris appended to with+= "; kernels/...", leaving a leading;. When the resulting string is forwarded toHfApi(...),huggingface_hubjoins its own fields with another;, producing an empty token in the middle of the User-Agent header.After the dedup/format step in
huggingface_hub, this leaves a trailing;in the final header, which strict HTTP clients (httpx ≥ 0.25) reject withLocalProtocolError: Illegal header value.This breaks any flow that triggers
_get_hf_api()without supplying auser_agent— most notably_get_available_versions(), which is hit whentransformersloadsfinegrained-fp8/deep-gemmkernels.Repro
End-to-end, the same bug surfaces as a crash when running a
transformersQwen3-VL-*-FP8model — the FP8 kernel fetch never completes.Fix
Build the system info as a separate
sys_infostring with no leading separator, then concatenate it onto any caller-supplieduser_agentwith a single;only when the caller-supplied part is non-empty.Tests
Added
test_user_agent_no_leading_or_empty_segmenttokernels/tests/test_user_agent.pycovering the three input shapes that previously triggered the bug (None,"",{}).