Skip to content

[Bug]: JsonConverters crashes on nullable Option values #1464

@adbre

Description

@adbre

Description

Generated JSON converters throw InvalidOperationException for null Option<T?> values

Steps to reproduce

Serializing any model with null nullable value-type Option<T?> properties throws InvalidOperationException: Nullable object must have a value.

using Adyen.Checkout.Models;
using System.Text.Json;

var request = new PaymentLinkRequest(
    amount: new Amount("EUR", 0),
    merchantAccount: "TestMerchant",
    reference: "test-ref",
    reusable: null   // any null nullable value-type parameter triggers the bug
);

// Throws InvalidOperationException: Nullable object must have a value.
var json = JsonSerializer.Serialize(request);

Actual behavior

System.InvalidOperationException: Nullable object must have a value is thrown from PaymentLinkRequestJsonConverter.WriteProperties when any nullable value-type Option<T?> property is set via the constructor with a null value.

Expected behavior

Null nullable values passed to the constructor should either be serialized as JSON null or omitted from the output, consistent with how reference-type properties are handled (which correctly check != null before writing).

Code snippet or screenshots (if applicable)

The bug is in the generated WriteProperties method in PaymentLinkRequest.cs. All nullable value-type properties follow this pattern:

// Current (broken) — crashes when Value is null
if (paymentLinkRequest._ReusableOption.IsSet)
    writer.WriteBoolean("reusable", paymentLinkRequest._ReusableOption.Value!.Value);

The Option<bool?>(null) has IsSet = true but Value is null, so accessing .Value!.Value throws.

Compare with how reference-type properties are correctly handled:

// Reference types correctly null-check before writing
if (paymentLinkRequest._CountryCodeOption.IsSet)
    if (paymentLinkRequest.CountryCode != null)
        writer.WriteString("countryCode", paymentLinkRequest.CountryCode);

Adyen .NET API Library version

34

.NET version

10

Operating System

Windows

Additional context

  • The root cause is in the OpenAPI-generated JSON converter code. Reference-type Option<T?> properties correctly null-check before writing, but value-type Option<T?> properties do not.
  • The constructor's implicit conversion from T? to Option<T?> means passing null sets IsSet = true with Value = null — this is by design in Adyen.Core.Option<T>, but the serializer doesn't account for it.
  • This is not isolated to PaymentLinkRequest. The same .Value!.Value pattern without null-checking exists in 1,362 occurrences across 726 generated model files. Any model with nullable value-type optional properties is affected.

What is the reason the SDK uses Option<T?> over simply T??

It feels awkward to that Option<bool?> can be IsSet but it's value being null. The only reason I can see is to tell the serializer to do include the property, but writing null in json output. But that is only meaningful if the Adyen API makes a distinction between null and omitted properties.

If that's the intended purpose, the json serializer must consider that the value of Option<T?> can be null.

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