From cf6d686fecfa3f0eae22eeb54de8f254da5f5aad Mon Sep 17 00:00:00 2001 From: chriscrosstalk <49691103+chriscrosstalk@users.noreply.github.com> Date: Thu, 23 Jul 2026 22:05:13 -0500 Subject: [PATCH] fix(benchmark): surface a clear reason when leaderboard submission fails (#1138) The submit flow discarded the real failure reason and always returned the generic "Failed to submit benchmark results." to the UI. The most common cause is the leaderboard's one-per-hour rate limit (HTTP 429), which left users with no idea why their submission failed or that retrying shortly would also fail. - benchmark_controller: return a clear, actionable message. Name the rate limit explicitly on 429; otherwise pass through the underlying detail (repository error or a service validation message like "already submitted"), falling back to the generic only when we have nothing. - benchmark_service: attach the raw upstream `detail` to the thrown error so the controller can surface it. The frontend already renders the server `error` string, so no client change is needed. --- admin/app/controllers/benchmark_controller.ts | 15 ++++++++++++++- admin/app/services/benchmark_service.ts | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/admin/app/controllers/benchmark_controller.ts b/admin/app/controllers/benchmark_controller.ts index 144bb54c..714c61a8 100644 --- a/admin/app/controllers/benchmark_controller.ts +++ b/admin/app/controllers/benchmark_controller.ts @@ -184,9 +184,22 @@ export default class BenchmarkController { // Pass through the status code from the service if available, otherwise default to 400 const statusCode = (error as any).statusCode || 400 logger.error({ err: error }, '[BenchmarkController] Benchmark submit failed') + + // Surface a clear, actionable reason to the UI instead of a generic failure. + // The rate limiter (429) is the most common cause, so name it explicitly; + // otherwise pass through the underlying detail (repository error or a service + // validation message) and fall back to a safe generic only when we have none. + let errorMessage: string + if (statusCode === 429) { + errorMessage = 'You can only submit one benchmark per hour. Please wait a bit and try again.' + } else { + errorMessage = + (error as any).detail || (error as any).message || 'Failed to submit benchmark results.' + } + return response.status(statusCode).send({ success: false, - error: 'Failed to submit benchmark results.', + error: errorMessage, }) } } diff --git a/admin/app/services/benchmark_service.ts b/admin/app/services/benchmark_service.ts index 03d1f1b9..0a6239ae 100644 --- a/admin/app/services/benchmark_service.ts +++ b/admin/app/services/benchmark_service.ts @@ -299,9 +299,11 @@ export class BenchmarkService { const statusCode = error.response?.status logger.error(`Failed to submit benchmark to repository: ${detail} (Status: ${statusCode})`) - // Create an error with the status code attached for proper handling upstream + // Create an error with the status code and raw detail attached for proper + // handling upstream (the controller surfaces `detail` as the user-facing reason). const err: any = new Error(`Failed to submit benchmark: ${detail}`) err.statusCode = statusCode + err.detail = detail throw err } }