Skip to content

[Bug]: Inline enum name collision with a component schema silently overwrites the model and breaks client imports #460

Description

@ALagoni97

Description

When an inline enum's inferred model name collides with a named component schema, both models are written to the same payload file. One silently overwrites the other, and the aggregate http_client.ts / client file then imports a symbol that no longer exists.

Generation reports zero errors — the breakage only appears when the generated package is type-checked.

This is more serious than the compile error suggests: a generated model is silently lost. In a spec where the two colliding models happen to be structurally compatible, there would be no type error at all, and the consumer would get the wrong model at runtime.

Reproduction

Two schemas whose generated names collide:

  • components.schemas.PackageType — an object (code, description, …), returned by GET /package_types
  • components.schemas.LoadCarrier.properties.package_type — an inline enum (PALLET, PARCEL, …), whose name Modelina infers from the property as PackageType
{
  "openapi": "3.0.1",
  "info": { "title": "Collision repro", "version": "1.0.0" },
  "paths": {
    "/package_types": {
      "get": {
        "operationId": "packageTypesGet",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/PackageType" }
                }
              }
            }
          }
        }
      }
    },
    "/load_carriers": {
      "get": {
        "operationId": "loadCarriersGet",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/LoadCarrier" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PackageType": {
        "type": "object",
        "properties": {
          "code": { "type": "string" },
          "description": { "type": "string" }
        }
      },
      "LoadCarrier": {
        "type": "object",
        "properties": {
          "package_type": {
            "type": "string",
            "enum": ["PALLET", "PARCEL", "BOX"]
          }
        }
      }
    }
  }
}

Config: channels (protocol http_client) + client (protocol http), the standard OpenAPI client pair from examples/openapi-http-client.

codegen generate && tsc --noEmit

Actual output

payload/PackageType.ts contains only the enum — the object model is gone:

enum PackageType {
  PALLET = 'PALLET',
  PARCEL = 'PARCEL',
  BOX = 'BOX'
}
export { PackageType };

Compare a non-colliding payload, which exports both:

export { PackagesItem };
export type { PackagesItemInterface };

http_client.ts then imports the same symbol twice — once for each model that thought it owned the file:

import { PackageType } from './payload/PackageType'; // line 123 — the enum
import { PackageType, PackageTypeInterface } from './payload/PackageType'; // line 246 — the object
TS2300: Duplicate identifier 'PackageType'.
TS2305: Module './payload/PackageType' has no exported member 'PackageTypeInterface'.

Six errors across http_client.ts and the generated client class — both entry-point files, so nothing downstream compiles.

Expected

Colliding names should be disambiguated so both models survive, and the aggregate imports should reference the disambiguated names.

The disambiguation logic already works elsewhere in the same run: an inline enum at PackagesItem.properties.package_type correctly became PackagesItemPackageType in its own file. The same spec produced a bare PackageType for LoadCarrier.properties.package_type, so the prefixing is applied inconsistently — that inconsistency is probably the root cause and the cheapest place to look.

Worth deciding as part of the fix: whether a name collision should be a hard generation error rather than a warning, since the silent-overwrite case is undetectable downstream.

Notes

The import dedup in generateHttpClient (src/codegen/generators/typescript/client/protocols/http.ts:172) uses [...new Set(dependencies)] on whole import strings, so two differently-shaped imports of the same symbol both survive. Deduping by symbol rather than by string would turn this into a single wrong-import error instead of a duplicate-identifier one — but that's a symptom, not the cause. The collision itself is the bug.

Environment

  • CLI version: 0.82.1 (built from source, matches published latest)
  • Node: 22
  • OS: Windows 11
  • Input: OpenAPI 3.0.1, 72 paths / 88 operations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions