Skip to content

fix(cli): resolve streaming request name collision when x-fern-type-name is set#14256

Merged
jsklan merged 9 commits intomainfrom
jsklan/fix-stream-request-collision
Apr 1, 2026
Merged

fix(cli): resolve streaming request name collision when x-fern-type-name is set#14256
jsklan merged 9 commits intomainfrom
jsklan/fix-stream-request-collision

Conversation

@jsklan
Copy link
Copy Markdown
Contributor

@jsklan jsklan commented Mar 28, 2026

Description

When a $ref request body schema has x-fern-type-name set and is used in a stream-condition endpoint, both the streaming and non-streaming request variants inherit the same nameOverride (e.g., "ChatRequest"), causing duplicate declaration errors downstream. This was introduced by #13568's auto-disambiguation logic, which unconditionally derived a streaming request name from the schema $ref path — even when x-fern-type-name wasn't present and the breadcrumb-based generatedName was already unique.

Changes Made

  • convertStreamingOperation.ts: Changed auto-disambiguation to only apply when the referenced schema has x-fern-type-name. Resolves the schema reference and checks for the extension — if present, uses ${typeName}Streaming as the override. Without it, the naturally differentiated generatedName from convertHttpOperation handles uniqueness via breadcrumbs.
  • New test fixture (x-fern-streaming-name-collision): Covers the collision case with a ChatRequest schema that has x-fern-type-name, plus multiple endpoints sharing the same $ref without x-fern-type-name.

Testing

  • All v3-importer-tests pass
  • All openapi-ir-to-fern-tests pass
  • Type-checks cleanly (tsc --noEmit)

@github-actions
Copy link
Copy Markdown
Contributor

🌱 Seed Test Selector

Select languages to run seed tests for:

  • Python
  • TypeScript
  • Java
  • Go
  • Ruby
  • C#
  • PHP
  • Swift
  • Rust
  • OpenAPI
  • Postman

How to use: Click the ⋯ menu above → "Edit" → check the boxes you want → click "Update comment". Tests will run automatically and snapshots will be committed to this PR.

@jsklan jsklan changed the title fix(openapi): resolve streaming request name collision when multiple … fix(cli): resolve streaming request name collision when multiple … Mar 28, 2026
@jsklan jsklan changed the title fix(cli): resolve streaming request name collision when multiple … fix(openapi): resolve streaming request name collision when multiple endpoints share a $ref body Mar 28, 2026
@jsklan jsklan requested a review from Swimburger March 28, 2026 00:09
@jsklan jsklan marked this pull request as ready for review March 30, 2026 14:20
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

@jsklan jsklan changed the title fix(openapi): resolve streaming request name collision when multiple endpoints share a $ref body fix(cli): resolve streaming request name collision when multiple endpoints share a $ref body Mar 30, 2026
@fern-support fern-support changed the title fix(cli): resolve streaming request name collision when multiple endpoints share a $ref body fix(cli): resolve streaming request name collision when x-fern-type-name is set Mar 30, 2026
@jsklan jsklan force-pushed the jsklan/fix-stream-request-collision branch from 3d69e7c to e8f523d Compare March 30, 2026 20:57
jsklan added 6 commits April 1, 2026 15:05
…endpoints share a $ref body

When two endpoints both use x-fern-streaming with stream-condition and
reference the same $ref request body schema, the auto-disambiguation
logic was deriving the streaming request name from the shared schema
name (e.g. NorthChatRequestInternalStreaming), causing duplicate
declaration errors.

Remove the ${schemaId}Streaming auto-disambiguation and instead let
convertHttpOperation's generatedRequestName (which is already unique
per endpoint via breadcrumbs with "stream" suffix) flow through as the
natural fallback. Explicit stream-request-name overrides still work.

Also adds multi-endpoint test coverage to the x-fern-streaming-with-reference
fixture to prevent regression.
@devin-ai-integration devin-ai-integration bot force-pushed the jsklan/fix-stream-request-collision branch from 70b1f5c to aa6eaa3 Compare April 1, 2026 15:06
devin-ai-integration bot and others added 3 commits April 1, 2026 15:09
Co-Authored-By: judah <jsklan.development@gmail.com>
Co-Authored-By: judah <jsklan.development@gmail.com>
Co-Authored-By: judah <jsklan.development@gmail.com>
@jsklan jsklan merged commit c146ac9 into main Apr 1, 2026
868 of 872 checks passed
@jsklan jsklan deleted the jsklan/fix-stream-request-collision branch April 1, 2026 20:02
fern-support pushed a commit that referenced this pull request Apr 10, 2026
…reaming test cases

Add endpoints 8-14 covering x-fern-streaming extension patterns that have
been the source of multiple regressions:

- Endpoint 8: basic stream-condition with $ref request body (#13568)
- Endpoint 9: stream-condition with x-fern-type-name (#14256)
- Endpoints 10-11: shared request schema across streaming/non-streaming (#14291)
- Endpoint 12: discriminated union request with allOf-inherited stream
  condition field, reproducing the Vectara regression (FER-9556, #14730)
- Endpoint 13: nullable stream condition field (#13605)
- Endpoint 14: x-fern-streaming with SSE format only (no stream-condition)
fern-support pushed a commit that referenced this pull request Apr 10, 2026
Endpoint 9's ChatCompletionRequest name collision blocks IR generation
for the entire fixture. Comment it out so the remaining endpoints can
be tested end-to-end. Uncomment when investigating the x-fern-type-name
disambiguation fix (PR #14256) in isolation.
jsklan added a commit that referenced this pull request Apr 10, 2026
… union variants (#14874)

* feat(seed): augment server-sent-events-openapi fixture with x-fern-streaming test cases

Add endpoints 8-14 covering x-fern-streaming extension patterns that have
been the source of multiple regressions:

- Endpoint 8: basic stream-condition with $ref request body (#13568)
- Endpoint 9: stream-condition with x-fern-type-name (#14256)
- Endpoints 10-11: shared request schema across streaming/non-streaming (#14291)
- Endpoint 12: discriminated union request with allOf-inherited stream
  condition field, reproducing the Vectara regression (FER-9556, #14730)
- Endpoint 13: nullable stream condition field (#13605)
- Endpoint 14: x-fern-streaming with SSE format only (no stream-condition)

* chore(seed): add debug script for SSE pipeline stage inspection

Runs the locally-built Fern CLI against the server-sent-events-openapi
fixture through each transformation stage (openapi-ir, write-definition,
ir), collecting outputs in .local/results/ for inspection. Continues
past failures so all stages produce output even when earlier ones error.

Usage: pnpm tsx scripts/debug-sse-pipeline.ts

* chore(seed): comment out endpoint 9 (x-fern-type-name collision)

Endpoint 9's ChatCompletionRequest name collision blocks IR generation
for the entire fixture. Comment it out so the remaining endpoints can
be tested end-to-end. Uncomment when investigating the x-fern-type-name
disambiguation fix (PR #14256) in isolation.

* fix: deduplicate stream condition properties in discriminated union variants

When a discriminated union's variants inherit the stream condition field
from a base schema via extends, the property appeared twice in generated
Python code — once from the union's base properties (pinned as a literal)
and once from the variant's extended properties (as boolean). This caused
SyntaxError: Duplicate keyword argument in generated wire tests and
pydantic model definitions.

Two fixes:
1. DynamicTypeLiteralMapper.ts: filter objectEntries that overlap with
   baseFields when building samePropertiesAsObject variant constructor args
2. simple_discriminated_union_generator.py: skip variant properties whose
   wire_value matches any union base property

Fixes FER-9556

Co-Authored-By: bot_apk <apk@cognition.ai>

* chore: update ir-to-jsonschema snapshots for server-sent-events-openapi fixture

Co-Authored-By: bot_apk <apk@cognition.ai>

* chore: add server-sent-events-openapi to go-sdk allowed failures

Co-Authored-By: bot_apk <apk@cognition.ai>

* fix: preserve AST references for streaming endpoint imports in wire tests

Co-Authored-By: bot_apk <apk@cognition.ai>

* style: fix biome formatting in WireTestGenerator.ts

Co-Authored-By: bot_apk <apk@cognition.ai>

* fix: escape triple quotes in docstrings and suppress mypy overload errors in exported client wrapper

Co-Authored-By: judah <jsklan.development@gmail.com>

* chore: update seed snapshot for exported client type ignore comment

Co-Authored-By: judah <jsklan.development@gmail.com>

* fix: use actual stream condition property name in WireMock body patterns

Instead of hardcoding 'stream' in the matchesJsonPath body pattern,
extract the actual stream condition property name from the SSE endpoint's
example request body. This fixes WireMock stub routing for APIs that use
a different property name (e.g. 'stream_response' in the Vectara API).

Co-Authored-By: judah <jsklan.development@gmail.com>

* fix: use explicit None check for mypy type narrowing in wrapper class

Co-Authored-By: judah <jsklan.development@gmail.com>

* fix: update CLI changelog version ordering and regenerate IR test snapshots

Co-Authored-By: judah <jsklan.development@gmail.com>

* nit

* fix(python): replace type: ignore with proper @overload signatures in exported client wrapper

Mirror the base client's @overload signatures on the wrapper class and
use **kwargs pass-through for super().__init__(), so mypy is satisfied
without suppressing the error.

---------

Co-authored-by: jsklan <jsklan.development@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
Co-authored-by: jsklan <100491078+jsklan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants