diff --git a/src/Core/Services/DabGraphQLResultSerializer.cs b/src/Core/Services/DabGraphQLResultSerializer.cs
index b9cce8334c..dac3f4aedb 100644
--- a/src/Core/Services/DabGraphQLResultSerializer.cs
+++ b/src/Core/Services/DabGraphQLResultSerializer.cs
@@ -11,10 +11,17 @@ namespace Azure.DataApiBuilder.Core.Services;
///
/// The DabGraphQLResultSerializer inspects the IExecutionResult created by HotChocolate
/// and determines the appropriate HTTP error code to return based on the errors in the result.
-/// By Default, without this serializer, HotChocolate will return a 500 status code when database errors
-/// exist. However, there is a specific error code we check for that should return a 400 status code:
-/// - DatabaseInputError. This indicates that the client can make a change to request contents to influence
-/// a change in the response.
+///
+/// By default, without this serializer, HotChocolate will return a 500 status code for errors.
+/// This serializer maps DataApiBuilderException.SubStatusCodes to their appropriate HTTP status codes.
+///
+/// For example:
+/// - Authentication/Authorization errors will return 401/403
+/// - Database input validation errors will return 400 BadRequest
+/// - Entity not found errors will return 404 NotFound
+///
+/// This ensures that GraphQL endpoints return appropriate and consistent HTTP status codes
+/// for all types of DataApiBuilderException errors.
///
public class DabGraphQLResultSerializer : DefaultHttpResultSerializer
{
@@ -22,9 +29,61 @@ public override HttpStatusCode GetStatusCode(IExecutionResult result)
{
if (result is IQueryResult queryResult && queryResult.Errors?.Count > 0)
{
- if (queryResult.Errors.Any(error => error.Code == DataApiBuilderException.SubStatusCodes.DatabaseInputError.ToString()))
+ // Check if any of the errors are from DataApiBuilderException by looking at error.Code
+ foreach (var error in queryResult.Errors)
{
- return HttpStatusCode.BadRequest;
+ if (error.Code != null &&
+ Enum.TryParse(error.Code, out var subStatusCode))
+ {
+ // Map SubStatusCodes to appropriate HTTP status codes
+ switch (subStatusCode)
+ {
+ // Authentication/Authorization errors
+ case DataApiBuilderException.SubStatusCodes.AuthenticationChallenge:
+ return HttpStatusCode.Unauthorized; // 401
+ case DataApiBuilderException.SubStatusCodes.AuthorizationCheckFailed:
+ case DataApiBuilderException.SubStatusCodes.DatabasePolicyFailure:
+ case DataApiBuilderException.SubStatusCodes.AuthorizationCumulativeColumnCheckFailed:
+ return HttpStatusCode.Forbidden; // 403
+
+ // Not Found errors
+ case DataApiBuilderException.SubStatusCodes.EntityNotFound:
+ case DataApiBuilderException.SubStatusCodes.ItemNotFound:
+ case DataApiBuilderException.SubStatusCodes.RelationshipNotFound:
+ case DataApiBuilderException.SubStatusCodes.RelationshipFieldNotFound:
+ case DataApiBuilderException.SubStatusCodes.DataSourceNotFound:
+ return HttpStatusCode.NotFound; // 404
+
+ // Bad Request errors
+ case DataApiBuilderException.SubStatusCodes.BadRequest:
+ case DataApiBuilderException.SubStatusCodes.DatabaseInputError:
+ case DataApiBuilderException.SubStatusCodes.InvalidIdentifierField:
+ case DataApiBuilderException.SubStatusCodes.ErrorProcessingData:
+ case DataApiBuilderException.SubStatusCodes.ExposedColumnNameMappingError:
+ case DataApiBuilderException.SubStatusCodes.UnsupportedClaimValueType:
+ case DataApiBuilderException.SubStatusCodes.ErrorProcessingEasyAuthHeader:
+ return HttpStatusCode.BadRequest; // 400
+
+ // Not Supported errors
+ case DataApiBuilderException.SubStatusCodes.NotSupported:
+ case DataApiBuilderException.SubStatusCodes.GlobalRestEndpointDisabled:
+ return HttpStatusCode.NotImplemented; // 501
+
+ // Conflict errors
+ case DataApiBuilderException.SubStatusCodes.OpenApiDocumentAlreadyExists:
+ return HttpStatusCode.Conflict; // 409
+
+ // Server errors - Internal Server Error
+ case DataApiBuilderException.SubStatusCodes.ConfigValidationError:
+ case DataApiBuilderException.SubStatusCodes.ErrorInInitialization:
+ case DataApiBuilderException.SubStatusCodes.DatabaseOperationFailed:
+ case DataApiBuilderException.SubStatusCodes.GraphQLMapping:
+ case DataApiBuilderException.SubStatusCodes.UnexpectedError:
+ case DataApiBuilderException.SubStatusCodes.OpenApiDocumentCreationFailure:
+ default:
+ return HttpStatusCode.InternalServerError; // 500
+ }
+ }
}
}