Visitar URL original
🐛 Fix explicit response_model ignored on streaming generator endpoints by MayankSharma-2812 · Pull Request #16384 · fastapi/fastapi · GitHub
Skip to content

🐛 Fix explicit response_model ignored on streaming generator endpoints - #16384

Open
MayankSharma-2812 wants to merge 1 commit into
fastapi:masterfrom
MayankSharma-2812:fix-streaming-explicit-response-model
Open

MayankSharma-2812 wants to merge 1 commit into
fastapi:masterfrom
MayankSharma-2812:fix-streaming-explicit-response-model

Conversation

@MayankSharma-2812

Copy link
Copy Markdown

Pull Request

Discussion: #16382

Description

When specifying an explicit response_model (such as response_model=Item, response_model=Iterator[Item], or response_model=AsyncIterable[Item]) on generator streaming endpoints (JSONL and SSE), it was ignored during response serialization and generated an empty OpenAPI itemSchema: {}.

Root Cause

In _populate_api_route_state(), get_stream_item_type() was only called when response_model was an instance of DefaultPlaceholder. When an explicit response_model was provided:

  1. route.stream_item_type was never populated, leaving stream_item_field as None.
  2. route.response_field was erroneously populated instead.
  3. At runtime, streaming endpoints serialize items via stream_item_field. Because it was None, serialization fell back to jsonable_encoder(), bypassing model validation and field filters (response_model_include, response_model_exclude, response_model_exclude_none).
  4. OpenAPI generation emitted an empty itemSchema: {} because stream_item_field was absent.

Fix

In _populate_api_route_state():

  • Check if the route is a streaming generator (is_sse_stream or is_json_stream) with an explicit response_model.
  • Extract the item model using get_stream_item_type(response_model) or response_model.
  • If it is not ServerSentEvent, assign route.stream_item_type = stream_item.
  • Set response_model = None so stream_item_field is created for per-item serialization, validation, and OpenAPI generation.

Tests Added

Added tests/test_stream_response_model.py covering:

  • Async JSONL stream with explicit model and field filtering (response_model_exclude, response_model_exclude_none)
  • Async JSONL stream with response_model=AsyncIterable[Item]
  • Sync generator JSONL stream with response_model=Iterator[Item]
  • SSE stream with explicit model and field exclusion
  • SSE stream yielding ServerSentEvent directly
  • SSE stream with explicit response_model=ServerSentEvent
  • Non-streaming endpoints unaffected
  • Validation error raised on invalid yielded chunk in async stream
  • Validation error raised on invalid yielded chunk in sync stream
  • Router inclusion via app.include_router()
  • OpenAPI schema generation (itemSchema for JSONL and contentSchema for SSE)

Checklist

  • This PR links to a GitHub Discussion for the proposed code change.
  • I added tests for the change.
  • The new or updated tests fail on the main branch and pass on this PR.
  • Coverage stays at 100%.
  • The documentation explains the change if needed.

@codspeed

codspeed Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing MayankSharma-2812:fix-streaming-explicit-response-model (e748591) with master (5f9fc5c)

Open in CodSpeed

@hossiendehghan989

This comment was marked as spam.

@MayankSharma-2812
MayankSharma-2812 force-pushed the fix-streaming-explicit-response-model branch from fa5380b to 311e187 Compare October 5, 2026 03:48
@MayankSharma-2812
MayankSharma-2812 force-pushed the fix-streaming-explicit-response-model branch from 311e187 to e748591 Compare October 5, 2026 03:57
@MayankSharma-2812

Copy link
Copy Markdown
Author

@hossiendehghan989 Great suggestion! Added regressions for response_model_by_alias on both JSONL and SSE streams using an explicit response_model with a serialization_alias="publicName".

The tests confirm that:

  1. By default (response_model_by_alias=True), streamed chunks serialize using the alias (publicName).
  2. With response_model_by_alias=False, streamed chunks serialize using the field name (name).

Both JSONL and SSE now have explicit coverage for this behavior. Pushed in the latest commit!

This branch has not been deployed

No deployments
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.

2 participants