Skip to content

fix: guidellm harness reports the real cause for an unsupported profile - #1683

Merged
maugustosilva merged 1 commit into
llm-d:mainfrom
UgaTheDev:fix/guidellm-replay-profile-guard
Jul 29, 2026
Merged

maugustosilva merged 1 commit into
llm-d:mainfrom
UgaTheDev:fix/guidellm-replay-profile-guard

Conversation

@UgaTheDev

@UgaTheDev UgaTheDev commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes #1510, specifically the misleading-error half of it (see the note at the end about the image pin).

profile: replay, and any other profile the installed guidellm doesn't know, fails inside guidellm's own argument parsing. The real error gets swallowed and resurfaces as something unrelated. Operators see:

Error: Missing field '--target': Field required

when the actual cause is:

Invalid value for --profile: Input should be 'synchronous', 'concurrent', 'throughput', 'constant' or 'poisson'

so they go and debug --target, which is fine.

This adds a pre-flight check to guidellm-llm-d-benchmark.sh that reads the workload's profile field and asks the installed guidellm which profiles it actually supports (a small python3 -c introspection of ProfileType | StrategyType) before guidellm is invoked. An unsupported profile now fails fast naming the real cause and the installed guidellm version. If the introspection fails for any reason it fails open, so the guard never blocks a run it couldn't validate, and a workload with no profile field is unaffected. The error goes to stderr, matching the precedent in lm-eval-llm-d-benchmark.sh.

On why the guard doesn't just pass --profile and let guidellm validate it: guidellm's --profile does validate against click.Choice(STRATEGY_PROFILE_CHOICES), but this harness hands the whole workload file over via --scenario and never passes --profile, so that built-in validation never runs. Reproducing the check in shell keeps the change inside one harness script and avoids depending on --scenario/--profile precedence that isn't documented.

Out of scope: bumping the guidellm pin so profile: replay actually works. replay currently only exists on guidellm's main branch (e.g. 73d91f311bd9). build/Dockerfile does install from a git commit rather than a PyPI release, so pinning a newer commit is technically possible today, but whether to ship an unreleased guidellm is a maintainer call rather than something this fix should decide.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Added tests/test_guidellm_profile_guard.py, which extracts the guard block from the shipped script itself (rather than a copy, so the test can't drift from the script) and runs it against fake yq, python3, and guidellm stubs. Four cases: unsupported profile fails with the real cause, supported profile passes through, a missing profile field doesn't block, and introspection failure fails open.

$ python3 -m pytest tests/test_guidellm_profile_guard.py -q
4 passed

Confirmed the tests actually fail without the change by reverting workload/harnesses/guidellm-llm-d-benchmark.sh to main and re-running: all four fail. Also ran bash -n on the script (syntax OK) and ruff check on the new test (clean).

Test Configuration

  • Kubernetes version: none. This change is confined to a harness shell script and a unit test that stubs out yq/python3/guidellm, so no cluster is involved in exercising it. I don't have a cluster available, so the full standup/run/teardown sequence was not run. Flagging that rather than claiming it.

Checklist

  • My changes follows the style guidelines of this project
  • I have performed a self-review of my own changes
  • I confirm that a full ./setup/standup.sh -> run.sh -> ./setup/teardown.sh sequence completed successfully
  • I confirm that pre-commit run was run and all checks passed
  • I have updated the documentation accordingly

On the two unchecked boxes: no cluster available here for the standup/run/teardown sequence, and pre-commit isn't installed in this environment, so I ran ruff check and pytest directly instead. Happy to have CI confirm both. No documentation change seemed warranted for an error-message fix, but say the word if you'd like the profile constraint written down somewhere.

@github-actions

Copy link
Copy Markdown
Contributor

Unsigned commits detected! Please sign your commits.

For instructions on how to set up GPG/SSH signing and verify your commits, please see GitHub Documentation.

@maugustosilva

Copy link
Copy Markdown
Collaborator

This looks good. Please sign all commits and we can merge. Thanks.

@UgaTheDev
UgaTheDev force-pushed the fix/guidellm-replay-profile-guard branch from dcb3be0 to b2def77 Compare July 28, 2026 16:07
profile: replay (and any other profile not yet supported by the
installed guidellm) fails inside guidellm's own argument parsing, but
the real error -- "Invalid value for --profile: ... 'synchronous',
'concurrent', 'throughput', 'constant' or 'poisson'" -- gets swallowed
and resurfaces as an unrelated "Missing field '--target': Field
required", sending operators off to debug the wrong thing.

Add a pre-flight check to guidellm-llm-d-benchmark.sh that reads the
workload's profile field and asks the installed guidellm (via a small
python3 -c introspection of ProfileType | StrategyType) which profiles
it actually supports, before guidellm is ever invoked. An unsupported
profile now fails fast with a message naming the actual cause and the
installed guidellm version, instead of a misleading Pydantic error.
Introspection failing for any reason fails open (the guard does not
block a run it can't validate), and a scenario with no profile field
is unaffected. The error goes to stderr, matching the existing
lm-eval-llm-d-benchmark.sh precedent for fatal harness errors.

guidellm's own --profile flag already validates against
click.Choice(STRATEGY_PROFILE_CHOICES) and would raise this same error
for free; the harness doesn't pass --profile because it hands the
whole workload file to guidellm via --scenario instead, so that
built-in validation never runs. Reproducing the check in shell (rather
than also passing --profile) keeps this fix confined to a single
harness script and avoids depending on --scenario/--profile precedence
behavior that isn't documented.

This only addresses the misleading error message. Bumping the
guidellm pin so profile: replay itself works is out of scope here --
replay support only exists on guidellm's main branch (e.g. commit
73d91f311bd9); build/Dockerfile already pins an arbitrary git commit
(not a PyPI release), so pinning a newer commit is possible, but
whether to ship an unreleased guidellm commit is a maintainer decision
and out of scope for this fix.

Adds tests/test_guidellm_profile_guard.py, which runs the guard block
extracted directly from the shipped script (not a copy) against fake
yq/python3/guidellm stubs.

Signed-off-by: Kush Zingade <[email protected]>
@UgaTheDev
UgaTheDev force-pushed the fix/guidellm-replay-profile-guard branch from b2def77 to 79b3678 Compare July 28, 2026 16:22
@UgaTheDev

Copy link
Copy Markdown
Contributor Author

Signed all commits and registered the SSH signing key on my account, so they verify now.

The earlier signed-commits failure ran a couple of minutes before I registered the key, so it was checking a signature GitHub couldn't attribute yet. Re-pushed to get a fresh run and it's green now.

Apologies for the force-push noise. Signing rewrites the commits, so the SHAs had to change; the diff itself is identical to what you reviewed.

@maugustosilva
maugustosilva merged commit 2c1e326 into llm-d:main Jul 29, 2026
27 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Benchmark image ships guidellm v0.6.0 which lacks replay profile support; error message is misleading

2 participants