Skip to content

[Detail Bug] SearchResponsePlace: NPE on deserialization when country/countryCode missing #57

@detail-app

Description

@detail-app

Detail Bug Report

https://app.detail.dev/org_befd6425-a158-4e24-9d4d-1e5c08769515/bugs/bug_e2b702e2-0ccd-49ec-ab52-58d0b7d23cef

Summary

  • Context: SearchResponsePlace.java is a record that represents a place returned by the Apple Maps Search API.
  • Bug: The country and countryCode fields are defined as mandatory String components and checked with Objects.requireNonNull in the constructor.
  • Actual vs. expected: The constructor throws a NullPointerException if country or countryCode is missing from the API response, whereas these fields should be optional to accommodate places in international waters or disputed territories.
  • Impact: Any search or reverse geocode request that returns a place without country information will cause the entire operation to fail with a NullPointerException during JSON deserialization.

Code with bug

00010| public record SearchResponsePlace(
...
00018|     String country,
00019|     String countryCode,
...
00036|     public SearchResponsePlace {
...
00045|         country = Objects.requireNonNull(country, "country"); // <-- BUG 🔴 [Mandatory check for potentially missing API field]
00046|         countryCode = Objects.requireNonNull(countryCode, "countryCode"); // <-- BUG 🔴 [Mandatory check for potentially missing API field]
00047|     }

Failing test

@Test
void deserializationFailsWhenCountryIsMissing() {
    String json = """
        {
          "name": "Test Place",
          "coordinate": {
            "latitude": 37.3349,
            "longitude": -122.0091
          },
          "countryCode": "US"
        }
        """;

    // This fails with NullPointerException because the record constructor requires 'country'
    objectMapper.readValue(json, SearchResponsePlace.class);
}

Output: com.fasterxml.jackson.databind.exc.ValueInstantiationException (caused by java.lang.NullPointerException: country)

Recommended fix

Change country and countryCode to Optional<String> and normalize in the constructor.

public record SearchResponsePlace(
    ...
    Optional<String> country, // <-- FIX 🟢
    Optional<String> countryCode, // <-- FIX 🟢
    ...
) {
    public SearchResponsePlace {
        ...
        country = normalizeOptional(country);
        countryCode = normalizeOptional(countryCode);
        ...
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions