Describe the bug
When parsing an invalid GraphQL schema, it is possible that the SchemaProblem exception thrown by SchemaGenerator will contain errors that have null source locations. i.e. GraphQLError.getLocations() can return a list containing nulls. When these GraphQLErrors are serialised via GraphQLError.toSpecification(), an NPE is thrown due to GraphQLErrorHelper.location() expecting a non-null SourceLocation argument.
To Reproduce
import graphql.GraphQLError;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.errors.SchemaProblem;
String sdl = """
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"])
type Query {
user: User
}
type User @key(fields: "id") {
id: ID!
}
""";
try {
SchemaGenerator.createdMockedSchema(sdl);
} catch (SchemaProblem e) {
e.getErrors().stream().map(GraphQLError::toSpecification).forEach(System.out::println);
}
The code inside the catch block will throw an NPE.
A test for the bug:
def "toSpecification filters out null error locations"() {
given:
def error = ValidationError.newValidationError()
.validationErrorType(ValidationErrorType.UnknownType)
.sourceLocations([null, mkLocation(333, 1)])
.description("Test ValidationError")
.build()
def expectedMap = [
locations: [
[line: 333, column: 1]
],
message: "Test ValidationError",
extensions: [classification:"ValidationError"]
]
expect:
error.toSpecification() == expectedMap
}
Potential solutions
A simple fix would be for BaseError.getLocations() to add an additional null check to node.getSourceLocation():
@Override
public List<SourceLocation> getLocations() {
return node == null || node.getSourceLocation() == null ? Collections.singletonList(NO_WHERE) : Collections.singletonList(node.getSourceLocation());
}
Or the potential of a nullable SourceLocation could be pushed further down into GraphQLErrorHelper:
public static Object location(SourceLocation location) {
if (location == null) {
return null;
}
int line = location.getLine();
int column = location.getColumn();
if (line < 1 || column < 1) {
return null;
}
return Map.of("line", line, "column", column);
}
Describe the bug
When parsing an invalid GraphQL schema, it is possible that the
SchemaProblemexception thrown bySchemaGeneratorwill contain errors that have null source locations. i.e.GraphQLError.getLocations()can return a list containing nulls. When these GraphQLErrors are serialised viaGraphQLError.toSpecification(), an NPE is thrown due toGraphQLErrorHelper.location()expecting a non-nullSourceLocationargument.To Reproduce
The code inside the catch block will throw an NPE.
A test for the bug:
Potential solutions
A simple fix would be for
BaseError.getLocations()to add an additional null check tonode.getSourceLocation():Or the potential of a nullable SourceLocation could be pushed further down into
GraphQLErrorHelper: