Skip to content

[BUG] Parsing a GetResult returns NPE if "found" field is missing #14519

@dbwiddis

Description

@dbwiddis

Describe the bug

GetResult.fromXContent(XcontentParser parser) throws a NullPointerException if the field "found" is missing.

This is an unexpected exception type for a parsing failure and can be confusing to developers. Other missing fields throw a ParsingException which developers are used to handling.

Related component

Libraries

To Reproduce

Run the following program.

import org.opensearch.action.get.GetResponse;
import org.opensearch.common.xcontent.LoggingDeprecationHandler;
import org.opensearch.common.xcontent.json.JsonXContent;
import org.opensearch.core.common.ParsingException;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.core.xcontent.XContentParser;

import java.io.IOException;

public class ReproTestCase {

    public static void main(String... args) {
        printExceptionType("{foo}");
        printExceptionType("{\"found\":false}");
        printExceptionType("{\"_index\":\"foo\",\"_id\":\"bar\"}");
    }

    static void printExceptionType(String json) {
        System.out.println("String to parse: " + json);
        try (
            XContentParser parser = JsonXContent.jsonXContent
                .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, json)
        ) {
            GetResponse.fromXContent(parser);
        } catch (IOException io) {
            System.out.println("  Bad JSON, expected IOException: " + io.getMessage());
        } catch (ParsingException p) {
            System.out.println("  Missing fields, expected ParsingException: " + p.getMessage());
        } catch (Exception e) {
            System.out.println("  Missing \"found\", unexpected Exception: " + e.getClass() + ", " + e.getMessage());
        }
        System.out.println();
    }

}

Output:

String to parse: "{foo}"
  Bad JSON, expected IOException: Unexpected character ('f' (code 102)): was expecting double-quote to start field name
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2]

String to parse: "{"found":false}"
  Missing fields, expected ParsingException: Missing required fields [_index,_id]

String to parse: "{"_index":"foo","_id":"bar"}"
  Missing "found", unexpected Exception: class java.lang.NullPointerException, null

Expected behavior

Code should either throw a ParsingException for a missing found field, or assume a sensible default (false) if it's omitted.

Additional Details

Additional context

The root cause of the problem is that found is initialized to null here:

And then only conditionally initialized:

} else if (FOUND.equals(currentFieldName)) {
found = parser.booleanValue();
} else {

This value is passed to the GetResult constructor which expects a primitive boolean for the exists parameter. Unboxing the null Boolean results in the NPE.

Suggested Fix

Option 1: test the value for null before calling the GetResult constructor, and throw a ParsingException.

Option 2: initialize found to false

Metadata

Metadata

Assignees

Labels

LibrariesLucene Upgrades and Libraries, Any 3rd party library that Core depends on, ex: nebula; team is respobugSomething isn't workinggood first issueGood for newcomers

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions