OpenAPITools / OpenAPITools/openapi-generator

[BUG][dart-dio] OAS 3.1 type: ["object", "null"] on inline object schema produces non-nullable Dart field

Open
#23,866 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • 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

When an OpenAPI 3.1 schema marks an inline object property as nullable via the array-form type: ["object", "null"], the dart-dio generator produces a non-nullable Dart field. The same null intent in other shapes is handled correctly:

Source schema Generated Dart field
type: ["object", "null"] on top-level / type-less data final Object? data;
nullable: true (OAS 3.0) final SomeType? data;
allOf: [$ref: ...] + nullable: true (OAS 3.0 idiom) final SomeType? data;
type: ["object", "null"] on inline object with properties: final InlineType data;

The last row is the bug. When the server actually returns data: null (which the spec explicitly allows), dio fails to deserialize and throws a DioException, which downstream callers misinterpret as a business error.

openapi-generator version

7.22.0 (via the Dart openapi_generator package).

OpenAPI declaration file content or url

Minimal repro:

openapi: 3.1.0
info:
  title: Repro
  version: "1.0"
paths:
  /login:
    post:
      operationId: login
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvelopeNullableLoginResponse"
components:
  schemas:
    EnvelopeNullableLoginResponse:
      type: object
      required: [code, data, message]
      properties:
        code:
          type: integer
        data:
          # this is the field that triggers the bug
          type:
            - object
            - "null"
          description: Business data; null on failure
          required:
            - token
          properties:
            token:
              type: string
        message:
          type: string
Generation Details
openapi-generator-cli generate -i spec.yaml -g dart-dio -o out --skip-validate-spec

No custom additionalProperties needed to reproduce. serializationLibrary set to either json_serializable or the default built_value shows the same Dart field type.

Steps to reproduce
  1. Save the spec above as spec.yaml.

  2. Run the generation command.

  3. Open out/lib/src/model/envelope_nullable_login_response.dart.

  4. Observe the data field:

    @JsonKey(name: r'data', required: true, includeIfNull: true)
    final EnvelopeNullableLoginResponseData data;   // expected: ...Data? data
    
  5. The synthesized inline class is generated correctly on its own — the bug is only that the outer field's type isn't suffixed with ?.

Related issues/PRs
  • #21565 — Dart-dio ignoring nullable references (nullableReferenceTypes: true). Overlapping symptom (nullable not honored), different trigger ($ref siblings, not array-form type). Both reduce to: dart-dio doesn't propagate isNullable to the field accessor in every code path.
  • #21510 — Dart incorrect nullable when required. Closely related — it's the OAS 3.0 nullable: true + required analog of this issue. The fix likely needs to cover both shapes.
  • #20827 — Same class of bug in the Java/Spring generator with type: [string, "null"], suggesting isNullable propagation has language-agnostic gaps for OAS 3.1 array-form null.
Suggest a fix

Best guess from reading the related issues: when the dart-dio templates compute the field type for an object whose schema has an inline type: [..., "null"] array form, the isNullable flag is not making it through to the place that emits the ? suffix. The detection of the synthesized inline class itself does work (the model file is generated), so the gap is between schema-level nullability detected and field-level accessor type rendered.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the dart-dio generator's nullable field-type handling and reproduce the issue using the provided OpenAPI declaration and generation command. Inspect out/lib/src/model/envelope_nullable_login_response.dart, compare the inline data field with the generated synthesized inline class and the nullable cases listed, and consider the issue done when data is emitted as a nullable Dart field for both supported serialization libraries.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
api, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.