081dc1a2de216d74a28252747d593c2b1288f251
max
  Tue May 26 02:06:08 2026 -0700
hubApi/botDelay: return JSON 500 when bottleneck server is unreachable

abortAndExplainConnectFail() previously called exit(0) directly after
writing raw HTML, which bypassed every error handler and produced a
broken response for JSON API clients.  Change it to errAbort() so it
can be caught by errCatch.

Wrap both hgBotDelayTimeFrac() call sites in hubApi (the global delay
in main() and the BLAT-specific extra delay in apiBlat()) in errCatch
blocks that call apiErrAbort(500) on failure, giving callers a proper
JSON error rather than an HTML fragment or a silent exit.

refs #36315

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

diff --git src/hg/lib/botDelay.c src/hg/lib/botDelay.c
index 11c9c21fa6f..e1200591629 100644
--- src/hg/lib/botDelay.c
+++ src/hg/lib/botDelay.c
@@ -13,46 +13,35 @@
 #include "hui.h"
 #include "hCommon.h"
 #include "botDelay.h"
 #include "jsonWrite.h"
 #include "regexHelper.h"
 #include "hubSpaceKeys.h"
 #include "cartDb.h"
 
 #define defaultDelayFrac 1.0   /* standard penalty for most CGIs */
 #define defaultWarnMs 10000    /* warning at 10 to 20 second delay */
 #define defaultExitMs 20000    /* error 429 Too Many Requests after 20+ second delay */
 
 int botDelayWarnMs  = 0;       /* global so the previously used value can be retrieved */
 
 void abortAndExplainConnectFail()
-/* Write out a short 500 response explaining that the connection to the
- * bottleneck server couldn't be established. Then exit. */
+/* Signal that the bottleneck server is unreachable.  Raises errAbort so that
+ * callers with an errCatch (e.g. hubApi JSON endpoints) can intercept and
+ * return a structured error instead of raw HTML. */
 {
-puts("Content-Type:text/html");
-printf("Status: 500 Interal Server Error\n");
-puts("\n");	/* blank line between header and body */
-
-puts("<!DOCTYPE HTML 4.01 Transitional>\n");
-puts("<html lang='en'>");
-puts("<head>");
-puts("<meta charset=\"utf-8\">");
-printf("<title>Status 500: Internal Server Error</title></head>\n");
-printf("<body><h1>Status 500: Internal Server Error</h1><p>\n");
-printf("Failed to connect to bottleneck server\n</p>");
-puts("</body></html>");
-exit(0);
+errAbort("Failed to connect to bottleneck server");
 }
 
 int botDelayTime(char *host, int port, char *botCheckString)
 /* Figure out suggested delay time for ip address in
  * milliseconds. */
 {
 int sd = netConnect(host, port);
 if (sd < 0)
     abortAndExplainConnectFail();
 char buf[256];
 netSendString(sd, botCheckString);
 netRecieveString(sd, buf);
 close(sd);
 return atoi(buf);
 }