Fix error propagation: surface API validation messages in the UI
- UseJsonExceptionHandler now maps InvalidOperationException to 400 (was 500), so upstream business-rule rejections reach the browser as actionable messages. - CvMatcherController forwards Refit 4xx bodies from cv-matcher-api instead of swallowing them in a generic 502. - ErrorResponse.Score removed; CaptchaController puts the score in Detail. - Frontend extractApiError helper reads the server Error/error/title field for 4xx responses and falls back to a generic i18n string for 5xx / missing body. - All four failure handlers (CV upload, CV match, contact form, subscribe form) updated to use extractApiError with the correct rate-limit i18n key. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -191,14 +191,35 @@ public static class StartupExtensions
|
||||
{
|
||||
var feature = context.Features.Get<IExceptionHandlerFeature>();
|
||||
var logger = context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(serviceName);
|
||||
|
||||
context.Response.ContentType = "application/json";
|
||||
|
||||
// InvalidOperationException signals an intentional business-rule violation
|
||||
// (e.g. "Could not extract enough job text"). Surface it as 400 with the
|
||||
// original message so the caller can show it directly to the user.
|
||||
if (feature?.Error is InvalidOperationException ioe)
|
||||
{
|
||||
logger.LogWarning(ioe, "Business rule violation in {Service}", serviceName);
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await context.Response.WriteAsJsonAsync(new Common.Responses.ErrorResponse
|
||||
{
|
||||
Error = ioe.Message,
|
||||
Code = "validation_error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (feature?.Error is not null)
|
||||
{
|
||||
logger.LogError(feature.Error, "Unhandled exception in {Service}", serviceName);
|
||||
}
|
||||
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
context.Response.ContentType = "application/json";
|
||||
await context.Response.WriteAsJsonAsync(new { error = "Unexpected server error." });
|
||||
await context.Response.WriteAsJsonAsync(new Common.Responses.ErrorResponse
|
||||
{
|
||||
Error = "Unexpected server error.",
|
||||
Code = "internal_error"
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user