Skip to content

[BUG][typescript-fetch] Adding new discriminators to polymorph classes breaks clients #20982

@aeneasr

Description

@aeneasr

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Let's say we are adding a new discriminator type to the API matching this description:

https://github.com/ory/kratos/blob/ef9ee235866c6f3958574d2e98f09de3ca1e83af/spec/api.json#L2452-L2462

Let's say it's

          "mapping": {
            "a": "#/components/schemas/uiNodeAnchorAttributes",
            "img": "#/components/schemas/uiNodeImageAttributes",
            "input": "#/components/schemas/uiNodeInputAttributes",
            "script": "#/components/schemas/uiNodeScriptAttributes",
            "text": "#/components/schemas/uiNodeTextAttributes",
+          "div": "#/components/schemas/uiNodeDivisionAttributes"
          },

If we have an SDK client generated prior to this change, and it tries to parse the request, we end up with an exception:

Error: No variant of UiNodeAttributes exists with 'node_type=div'
    at UiNodeAttributesFromJSONTyped (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiNodeAttributes.js:44:19)
    at UiNodeAttributesFromJSON (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiNodeAttributes.js:26:12)
    at UiNodeFromJSONTyped (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiNode.js:81:71)
    at UiNodeFromJSON (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiNode.js:74:12)
    at Array.map (<anonymous>)
    at UiContainerFromJSONTyped (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiContainer.js:46:33)
    at UiContainerFromJSON (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/UiContainer.js:36:12)
    at LoginFlowFromJSONTyped (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/LoginFlow.js:86:53)
    at LoginFlowFromJSON (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/models/LoginFlow.js:63:12)
    at JSONApiResponse.transformer (/Users/aeneas/workspace/go/cloud-shard-1/sdktest/node_modules/@ory/client-fetch/dist/apis/FrontendApi.js:307:103)
openapi-generator version

7.12.0

OpenAPI declaration file content or url

https://github.com/ory/kratos/blob/ef9ee235866c6f3958574d2e98f09de3ca1e83af/spec/api.json

Generation Details

We have enabled enumUnknownDefaultCase in the generator config:

npmName: "${NPM_NAME}-fetch"
npmVersion: $VERSION
# typescriptThreePlus: true
supportsES6: true
ensureUniqueParams: true
modelPropertyNaming: original
disallowAdditionalPropertiesIfNotPresent: false
withInterfaces: false
useSingleRequestParameter: true
enumUnknownDefaultCase: true
Steps to reproduce

test.js

const nock = require('nock');
const f = require('@ory/client-fetch');

const body = {
    "id": "830d9a9a-56a1-4569-b093-73e290a88660",
    "type": "browser",
    "expires_at": "2025-03-05T10:53:48.504179456Z",
    "issued_at": "2025-03-05T09:53:48.504179456Z",
    "request_url": "https://jolly-napier-yycikmm17f.projects.oryapis:8080/self-service/registration/browser",
    "ui": {
        "action": "https://jolly-napier-yycikmm17f.projects.oryapis:8080/self-service/registration?flow=830d9a9a-56a1-4569-b093-73e290a88660",
        "method": "POST",
        "nodes": [
            {
                "type": "div",
                "group": "captcha",
                "attributes": {
                    "id": "captcha_turnstile_inject",
                    "node_type": "div"
                },
                "messages": [],
                "meta": {}
            }
        ]
    },
    "organization_id": null,
    "state": "choose_method"
}


const oryf = new f.FrontendApi(
    new f.Configuration({
        basePath: 'http://localhost:4455',
    })
);

// Set up the mock endpoint for createNativeLoginFlow
nock('http://localhost:4455')
    .get("/self-service/login/api")
    .reply(200,body
    );

// Set up the mock endpoint for createNativeLoginFlow
nock('http://localhost:4455')
    .get("/self-service/login/browser")
    .reply(200, body)

oryf.createNativeLoginFlow({}).then((res) => {
    console.log(res);
});

oryf.createBrowserLoginFlow({}).then((res) => {
    console.log(res);
});

package.json

{
  "dependencies": {
    "@ory/client-fetch": "1.19.0",
    "nock": "^14.0.1"
  }
}
Related issues/PRs

Could not find any. However, in the regular typescript generator (with axios) this problem does not exist.

Suggest a fix

If a mapping or field is unknown, the client code should never break, otherwise it is impossible to make additive changes to an existing API.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions