litellm/tests/unit/enterprise
zoveki a1f3dcd01b
fix(completion)!: answer 400 for a chat message without a role (#51124)
* fix(completion): answer 400 for a chat message without a role

A message with no role was filled with role assistant and sent upstream, so the caller's text reached the
model as its own earlier reply and the request returned 200. Now a missing, null, or empty role answers 400
with OpenAI's wording, naming the message index. A role-less turn that carries tool_calls is still sent as
assistant, since only an assistant writes tool calls.

* fix(completion): treat a role-less message as the caller's error

The 400 now raises MalformedRequestFieldError with OpenAI's param and code and the provider name, so it no longer counts toward the deployment's failure rate, cools it down, or fires an llm_exceptions alert

* fix(completion): keep the assistant fill for a role-less function_call turn

* refactor(completion): type the role-less call turn check and the request kwargs

Read role, tool_calls and function_call off the cleaned message copy, and validate completion's kwargs into a typed mapping before naming the provider on the 400

* fix(completion): keep the alert and failure-count exclusions to the role error

Raise MissingMessageRoleError, a MalformedRequestFieldError subclass, so a malformed tools 400 alerts and counts as on main, and fill assistant whenever a role-less turn has a tool_calls or function_call key

* fix(completion): keep assistant-only role-less turns and skip SDK and PagerDuty alerts

A role-less turn carrying any assistant-only key, null values included, is still
filled as assistant, so a dumped assistant message or a reasoning turn keeps working.
The Router's alerting_config alert and the PagerDuty failure count skip the role error,
like the proxy alert already does.

* fix(utils): drop the string code from the missing-role 400 so the Errors tab counts it as 400

The spend log stored code missing_required_parameter as the error code, which
the Usage page Errors tab cannot parse as a status, so every role-less request
landed under no status. The malformed tools 400 leaves code out the same way.

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-11-11 20:59:19 +00:00
..
enterprise_callbacks fix(completion)!: answer 400 for a chat message without a role (#51124) 2026-11-11 20:59:19 +00:00
integrations refactor(typing): clear about 1,100 basedpyright Any errors across 303 files (#49986) 2026-11-06 13:31:15 -08:00
proxy feat(proxy): let teams use their own allowed S3 buckets for batch files (#50571) 2026-11-10 11:06:17 -08:00
__init__.py test: add __init__.py to migrated tests/unit packages 2026-09-20 11:53:49 +00:00
conftest.py ci: move caching, proxy-extras, gateway and enterprise tests into tests/unit and run them from litellm-tests (#42902) 2026-09-24 15:49:59 -07:00