Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace HotChocolate.Execution.Relay;

public sealed class NodeIdInvalidValueException(string typeName, object value)
: GraphQLException(ErrorBuilder.New()
.SetMessage(
$"The value could not be formatted into an ID for the type `{typeName}`.")
.SetExtension("originalValue", value.ToString())
.Build());
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public OperationContext ReportError(
{
foreach (var error in ex.Errors)
{
context.ReportError(error, resolverContext);
context.ReportError(
error.Path is null ? error.WithPath(path) : error,
resolverContext);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private static unsafe string Format(

Clear(rentedBuffer);

throw new NodeIdInvalidFormatException(internalId);
throw new NodeIdInvalidValueException(s_utf8.GetString(typeName), internalId);

static string FormatBase64(
ReadOnlySpan<byte> typeName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ public unsafe string Format(object value)

Clear(rentedBuffer);

throw new NodeIdInvalidFormatException(value);
throw new NodeIdInvalidValueException(typeName, value);
}

private string FormatBase64(Span<byte> span, int written, bool urlSafeBase64, ref byte[]? rentedBuffer, int capacity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,13 @@
"column": 54
}
],
"extensions": {
"code": "HC0001",
"coordinate": "boom.arg"
}
},
{
"message": "Cannot return null for non-nullable field.",
"path": [
"nestedObjectOutput",
"inner"
],
"extensions": {
"code": "HC0018"
"code": "HC0001",
"coordinate": "boom.arg"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@
"column": 70
}
],
"extensions": {
"code": "HC0001",
"coordinate": "boom.arg"
}
},
{
"message": "Cannot return null for non-nullable field.",
"path": [
"nestedObjectOutput",
"nestedObject",
"inner"
],
"extensions": {
"code": "HC0018"
"code": "HC0001",
"coordinate": "boom.arg"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,13 @@
"column": 46
}
],
"extensions": {
"code": "HC0001",
"coordinate": "boom.arg"
}
},
{
"message": "Cannot return null for non-nullable field.",
"path": [
"nestedObjectOutput",
"inner"
],
"extensions": {
"code": "HC0018"
"code": "HC0001",
"coordinate": "boom.arg"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,13 @@
"column": 68
}
],
"extensions": {
"code": "HC0001",
"coordinate": "boom.arg"
}
},
{
"message": "Cannot return null for non-nullable field.",
"path": [
"nestedObjectOutput",
"inner"
],
"extensions": {
"code": "HC0018"
"code": "HC0001",
"coordinate": "boom.arg"
}
}
],
Expand Down
132 changes: 132 additions & 0 deletions src/HotChocolate/Core/test/Types.Tests/Types/Relay/IdAttributeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,138 @@ public async Task EnsureIdIsOnlyAppliedOnce()
}

[SuppressMessage("Performance", "CA1822:Mark members as static")]
[Fact]
public async Task Bare_Id_On_Properties_With_Different_Runtime_Types()
{
// arrange & act
var result =
await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<ThingQuery>()
.AddGlobalObjectIdentification(false)
.ExecuteRequestAsync(
OperationRequestBuilder.New()
.SetDocument(
"""
{
thing {
id
anotherTypeId
}
}
""")
.Build());

// assert
result.ToJson().MatchInlineSnapshot(
"""
{
"errors": [
{
"message": "The value could not be formatted into an ID for the type `Thing`.",
"path": [
"thing",
"anotherTypeId"
],
"extensions": {
"originalValue": "26a2dc8f-4dab-408c-88c6-523a0a89a2b5"
}
}
],
"data": null
}
""");
}

[Fact]
public async Task Invalid_Id_Does_Not_Erase_Sibling_Data()
{
// arrange & act
var result =
await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<ProbeQuery>()
.AddGlobalObjectIdentification(false)
.ExecuteRequestAsync(
"""
{
byId(id: "invalid")
unrelated
}
""");

// assert
result.ToJson().MatchInlineSnapshot(
"""
{
"errors": [
{
"message": "The node ID string has an invalid format.",
"path": [
"byId"
],
"extensions": {
"originalValue": "invalid"
}
}
],
"data": {
"byId": null,
"unrelated": "value"
}
}
""");
}

[Fact]
public async Task Invalid_Id_On_Skipped_Field_Does_Not_Error()
{
// arrange & act
var result =
await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<ProbeQuery>()
.AddGlobalObjectIdentification(false)
.ExecuteRequestAsync(
"""
{
byId(id: "invalid") @skip(if: true)
unrelated
}
""");

// assert
result.ToJson().MatchInlineSnapshot(
"""
{
"data": {
"unrelated": "value"
}
}
""");
}

public class ProbeQuery
{
public int? GetById([ID] int id) => id;

public string GetUnrelated() => "value";
}

public class ThingQuery
{
public Thing GetThing() => new();
}

public class Thing
{
[ID]
public int Id { get; set; } = 1;

[ID]
public Guid AnotherTypeId { get; set; } = new("26a2dc8f-4dab-408c-88c6-523a0a89a2b5");
}

public class Query
{
public int IntId([ID] int id) => id;
Expand Down

This file was deleted.

Loading