Skip to content

Conversation

@jsklan
Copy link
Contributor

@jsklan jsklan commented Jan 8, 2026

Description

Refs: SDK Generation Bug Fix workflow (steps 1 and 2 of 3)

This PR adds a minimal seed test fixture that reproduces a wire test failure in the TypeScript SDK when using additionalProperties: true in OpenAPI schemas with the serialization layer enabled, and includes the manual fix showing the expected generated output.

Link to Devin run (step 1): https://app.devin.ai/sessions/5880724094f6499a8d50c183dcd924f0
Link to Devin run (step 2): https://app.devin.ai/sessions/2d09f0fdb5fb48c2b2301ce956b3c44d
Requested by: @jsklan

Changes Made

  • Added new test fixture ts-passthrough-additional-properties in test-definitions/fern/apis/
  • Added fixture configuration in seed/ts-sdk/seed.yml with noSerdeLayer: false
  • Generated seed output demonstrating the bug
  • Added ir-to-jsonschema snapshot for the new fixture
  • Added Swift SDK formatEndpointPathForSwift snapshot for the new fixture
  • Added fixture to allowedFailures in seed/ts-sdk/seed.yml for CI to pass
  • Manually fixed src/core/schemas/builders/object/object.ts to show expected behavior

Manual Fixes Applied (Step 2)

File changed: seed/ts-sdk/ts-passthrough-additional-properties/src/core/schemas/builders/object/object.ts

What was fixed: The passthrough() method in the object schema was spreading all raw properties first, then spreading transformed properties. This caused both snake_case (raw) and camelCase (transformed) versions of properties to appear in the result.

The fix: Filter out raw properties that were already processed before spreading, so only truly additional properties pass through:

const rawPropertiesSet = new Set<string>(
    schema._getRawProperties().map((p) => p as string),
);
const extraProperties: Record<string, unknown> = {};
for (const [key, value] of Object.entries(raw as object)) {
    if (!rawPropertiesSet.has(key)) {
        extraProperties[key] = value;
    }
}
return {
    ok: true,
    value: {
        ...extraProperties,
        ...transformed.value,
    } as Parsed & { [key: string]: unknown },
};

Note: The initial fix attempt using filterObject() caused TypeScript compilation errors due to type constraints. The manual loop approach with explicit type assertion resolves this.

Handoff Context (for next session - Step 3)

Bug Summary: When an OpenAPI schema has additionalProperties: true, the generated serialization layer uses .passthrough() which causes both camelCase and snake_case versions of properties to appear in the deserialized response.

Key insight: The passthrough() method spreads raw first (containing snake_case keys like user_name), then spreads transformed.value (containing camelCase keys like userName). The fix is to filter raw to only include keys that are NOT in the schema's raw properties list before spreading.

Files to investigate in generator:

  • generators/typescript/utils/core-utilities/src/core/schemas/builders/object/object.ts - The source file for the passthrough() method (lines 272-312). This needs the same fix applied.
  • generators/typescript/model/type-schema-generator/src/object/GeneratedObjectTypeSchemaImpl.ts - Where .passthrough() is called when this.shape.extraProperties is true (lines 41-43).

Validation command: pnpm seed:local test --generator ts-sdk --fixture ts-passthrough-additional-properties

Testing

  • Verified bug manifests with validation command (before fix)
  • Wire test passes after manual fix (399 tests pass)
  • pnpm build passes (both CJS and ESM)
  • ir-to-jsonschema snapshot generated and committed
  • Swift SDK formatEndpointPathForSwift snapshot generated and committed
  • Added fixture to allowedFailures for CI

Human Review Checklist

  • Verify the manual fix in object.ts correctly filters out processed raw keys
  • Confirm the type assertion as Parsed & { [key: string]: unknown } is safe
  • Note: The json method still uses ...(parsed as any) - may need similar fix in step 3
  • Confirm the fix doesn't break other passthrough scenarios (truly additional properties should still pass through)
  • Verify the minimal OpenAPI spec correctly captures the bug scenario

…trating wire test failure with additionalProperties

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration bot changed the title test(ts-sdk): add ts-passthrough-additional-properties fixture demonstrating wire test failure chore(seed): add ts-passthrough-additional-properties fixture demonstrating wire test failure Jan 8, 2026
devin-ai-integration bot and others added 4 commits January 8, 2026 18:41
…nal-properties fixture

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
…-passthrough-additional-properties fixture

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
…t to show expected result

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title chore(seed): add ts-passthrough-additional-properties fixture demonstrating wire test failure test(ts-sdk): add ts-passthrough-additional-properties fixture with manual fix Jan 8, 2026
devin-ai-integration bot and others added 3 commits January 8, 2026 19:29
…hrough-additional-properties

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
When an OpenAPI schema has additionalProperties: true, the passthrough()
method was spreading all raw properties first, then spreading transformed
properties. This caused both snake_case (raw) and camelCase (transformed)
versions of properties to appear in the deserialized response.

The fix filters the raw object to only include keys that are NOT in the
schema's raw properties list before spreading, so only truly additional
properties pass through.

Also removes ts-passthrough-additional-properties from allowedFailures
since it now passes.

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

Co-Authored-By: judah@buildwithfern.com <jsklan.development@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title test(ts-sdk): add ts-passthrough-additional-properties fixture with manual fix fix(typescript): filter out processed raw keys in passthrough schema Jan 8, 2026
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