0a5f9cb363719d91237e0ec3c4b8831ad447daca
max
  Thu Sep 10 06:45:33 2026 -0700
hgTrackUi: a missing track name is bad input, not a stack dump, refs #38192

hgTrackUi aborts when the URL carries no g= parameter, which happens with
a hand-edited or truncated address and with the crawlers that trim query
strings. errAbort routes that through the stack dump handler, so hg.conf
browser.dumpStack turns each one into a gdb backtrace in the error log
and about a third of a second of wait4. hUserAbort exists for errors that
come from user input: same message on the page, one line in the log.

diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c
index c87a7ebbee7..3bce7c78fa0 100644
--- src/hg/hgTrackUi/hgTrackUi.c
+++ src/hg/hgTrackUi/hgTrackUi.c
@@ -4582,34 +4582,35 @@
 char *ignored;
 
 /* used to have hgBotDelayFrac(0.25) here, replaced with earlyBotCheck()
  * at the beginning of main() to output message here if in delay time
  * 2021-06-21 - Hiram
  */
 if (issueBotWarning)
     {
     char *ip = getenv("REMOTE_ADDR");
     botDelayMessage(ip, botDelayMillis);
     }
 
 cart = theCart;
 /* The track name is not kept in the cart, so it has to come with the request.  Without it
  * there is no page to draw, and saying so beats the bare hash lookup failure that a
- * hand-edited or truncated URL used to produce. */
+ * hand-edited or truncated URL used to produce.  A missing parameter is bad input rather
+ * than a program error, so hUserAbort, which keeps it out of the stack dumps. */
 track = cartOptionalString(cart, "g");
 if (isEmpty(track))
-    errAbort("This page needs to know which track to show, and the address it was reached by "
+    hUserAbort("This page needs to know which track to show, and the address it was reached by "
                "does not name one.  Open a track's settings from the browser, or add the track "
                "name to the address with the g parameter, e.g. hgTrackUi?db=hg38&g=knownGene");
 getDbAndGenome(cart, &database, &ignored, NULL);
 initGenbankTableNames(database);
 chromosome = cartUsualString(cart, "c", hDefaultChrom(database));
 trackHash = trackHashMakeWithComposites(database,chromosome,&tdbList,FALSE); 
 
 /* Handle dup of track related stuff */
 char *dupeName = handleDupOp(track, trackHash);
 if (dupeName != NULL)
     track = dupeName;
 struct dupTrack *dupList = dupTrackListFromCart(cart);
 char *dupWholeName = NULL;
 boolean isDup = isDupTrack(track);
 if (isDup)