e389c29f0255935bc714c66ce7182c4a24427adc
braney
  Fri Feb 6 12:13:44 2026 -0800
fixes hubApi trackDb cache bug #37064

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index 41d484bd010..c1ca666f008 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -73,42 +73,42 @@
 if (columnCount > 6)
     jsonWriteNumber(jw, columnNames[i++], (long long)el->priority);
 if (columnCount > 7)
     jsonWriteString(jw, columnNames[i++], el->clade);
 jsonWriteObjectEnd(jw);
 }
 
 static void dbDbJsonData(struct jsonWrite *jw, struct dbDb *el,
     int columnCount, char **columnNames)
 /* Print out dbDb table element in JSON format.
  * must be same as was stated in the columnName header element
  * This code should be over in hg/lib/dbDb.c
  */
 {
 int i = 0;
-jsonWriteObjectStart(jw, el->name);
+jsonWriteObjectStart(jw, trackHubSkipHubName(el->name));
 i++;
 // redundant: jsonWriteString(jw, NULL, el->name);
 jsonWriteString(jw, columnNames[i++], el->description);
 jsonWriteString(jw, columnNames[i++], el->nibPath);
 jsonWriteString(jw, columnNames[i++], el->organism);
 jsonWriteString(jw, columnNames[i++], el->defaultPos);
 jsonWriteNumber(jw, columnNames[i++], (long long)el->active);
 jsonWriteNumber(jw, columnNames[i++], (long long)el->orderKey);
 jsonWriteString(jw, columnNames[i++], el->genome);
 jsonWriteString(jw, columnNames[i++], el->scientificName);
-jsonWriteString(jw, columnNames[i++], el->htmlPath);
+jsonWriteString(jw, columnNames[i++], trackHubSkipHubName(el->htmlPath));
 jsonWriteNumber(jw, columnNames[i++], (long long)el->hgNearOk);
 jsonWriteNumber(jw, columnNames[i++], (long long)el->hgPbOk);
 jsonWriteString(jw, columnNames[i++], el->sourceName);
 jsonWriteNumber(jw, columnNames[i++], (long long)el->taxId);
 jsonWriteObjectEnd(jw);
 }
 
 static void jsonDbDb()
 /* output the dbDb SQL table */
 {
 char *extraArgs = verifyLegalArgs(argListUcscGenomes); /* no extras allowed */
 if (extraArgs)
     apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/ucscGenomes '%s'", extraArgs);
 
 struct sqlConnection *conn = hConnectCentral();
@@ -200,31 +200,31 @@
 static void hubChromInfoJsonOutput(FILE *f, char *hubUrl, char *genome)
 /* for given hubUrl list the chromosomes in the sequence for specified genome
  */
 {
 struct trackHub *hub = errCatchTrackHubOpen(hubUrl);
 struct trackHubGenome *ge = NULL;
 char *track = cgiOptionalString("track");
 
 if (isEmpty(genome))
     apiErrAbort(err400, err400Msg, "must specify a 'genome=name' with hubUrl for endpoint: /list/chromosomes?hubUrl=%s;genome=<empty>", hubUrl);
 
 struct trackHubGenome *foundGenome = NULL;
 
 for (ge = hub->genomeList; ge; ge = ge->next)
     {
-    if (sameOk(genome, ge->name))
+    if (sameOk(genome, trackHubSkipHubName(ge->name)))
 	{
 	foundGenome = ge;
 	continue;	/* found genome */
 	}
     }
 
 if (NULL == foundGenome)
     apiErrAbort(err400, err400Msg, "can not find specified 'genome=%s' for endpoint: /list/chromosomes?hubUrl=%s;genome=%s", genome, hubUrl, genome);
 
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "hubUrl", hubUrl);
 jsonWriteString(jw, "genome", genome);
 if (isNotEmpty(track))
     {
     jsonWriteString(jw, "track", track);
@@ -394,49 +394,49 @@
     {
     struct hashEl *hel;
     struct hashCookie hc = hashFirst(tdb->settingsHash);
     while ((hel = hashNext(&hc)) != NULL)
         {
         if (sameWord("track", hel->name))
             continue;	// already output in header
         if (sameWord("tableBrowser", hel->name)
 		&& startsWithWord("off", (char*)hel->val))
             jsonWriteBoolean(jw, "protectedData", TRUE);
         else if (isEmpty((char *)hel->val))
             jsonWriteString(jw, hel->name, "empty");
         else if (protectedData && sameWord(hel->name, "bigDataUrl"))
             jsonWriteString(jw, hel->name, "protectedData");
         else
-            jsonWriteString(jw, hel->name, (char *)hel->val);
+            jsonWriteString(jw, hel->name, trackHubSkipHubName((char *)hel->val));
         }
     }
 }
 
 static void hubSchemaJsonOutput(FILE *f, char *hubUrl, char *genome, char *track)
 /* for given hubUrl and track, output the schema for the hub track */
 {
 struct trackHub *hub = errCatchTrackHubOpen(hubUrl);
 struct trackHubGenome *ge = NULL;
 
 if (isEmpty(genome))
     apiErrAbort(err400, err400Msg, "must specify a 'genome=name' with hubUrl for endpoint: /list/schema?hubUrl=%s;genome=<empty>", hubUrl);
 
 struct trackHubGenome *foundGenome = NULL;
 
 for (ge = hub->genomeList; ge; ge = ge->next)
     {
-    if (sameOk(genome, ge->name))
+    if (sameOk(genome, trackHubSkipHubName(ge->name)))
 	{
 	foundGenome = ge;
 	continue;	/* found genome */
 	}
     }
 
 if (NULL == foundGenome)
     apiErrAbort(err400, err400Msg, "can not find specified 'genome=%s' for endpoint: /list/schema?hubUrl=%s;genome=%s", genome, hubUrl, genome);
 
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "hubUrl", hubUrl);
 jsonWriteString(jw, "genome", genome);
 jsonWriteString(jw, "track", track);
 
 struct trackDb *tdb = obtainTdb(foundGenome, NULL);
@@ -1024,31 +1024,31 @@
 /* output trackDb tags only for real tracks, not containers,
  * recursive when subtracks exist
  */
 {
 boolean isContainer = trackHasNoData(tdb);
 
 /* do *NOT* print containers when 'trackLeavesOnly' requested */
 if (! (trackLeavesOnly && isContainer) )
     {
 #ifdef NOTNOW
     long long itemCount = 0;
     /* do not show counts for protected data or continers (== no items)*/
     if (! (isContainer || protectedTrack(db, tdb, tdb->track)))
 	itemCount = dataItemCount(db, tdb);
 #endif
-    jsonWriteObjectStart(jw, tdb->track);
+    jsonWriteObjectStart(jw, trackHubSkipHubName(tdb->track));
     if (tdbIsComposite(tdb))
         jsonWriteString(jw, "compositeContainer", "TRUE");
     if (tdbIsCompositeView(tdb))
         jsonWriteString(jw, "compositeViewContainer", "TRUE");
     outputTrackDbVars(jw, db, tdb, -1);
 
     if (tdb->subtracks)
 	{
 	struct trackDb *el = NULL;
 	for (el = tdb->subtracks; el != NULL; el = el->next )
 	    recursiveTrackList(jw, el, db);
 	}
 
     jsonWriteObjectEnd(jw);
     }
@@ -1118,32 +1118,32 @@
 
     char *hubUrl = cgiOptionalString("hubUrl");
     if (isEmpty(hubUrl))
 	apiErrAbort(err400, err400Msg, "must supply hubUrl='http:...' some URL to a hub for /list/hubGenomes");
 
     struct trackHub *hub = errCatchTrackHubOpen(hubUrl);
     if (hub->genomeList)
 	{
 	trackHubGenomeNameSort(&hub->genomeList);
         struct jsonWrite *jw = apiStartOutput();
 	jsonWriteString(jw, "hubUrl", hubUrl);
         jsonWriteObjectStart(jw, "genomes");
 	struct trackHubGenome *el;
         for ( el = hub->genomeList; el; el = el->next)
 	    {
-	    jsonWriteObjectStart(jw, el->name);
-	    jsonWriteString(jw, "organism", el->organism);
+	    jsonWriteObjectStart(jw, trackHubSkipHubName(el->name));
+	    jsonWriteString(jw, "organism", trackHubSkipHubName(el->organism));
 	    jsonWriteString(jw, "description", el->description);
 	    jsonWriteString(jw, "trackDbFile", el->trackDbFile);
 	    jsonWriteString(jw, "twoBitPath", el->twoBitPath);
 	    jsonWriteString(jw, "groups", el->groups);
 	    jsonWriteString(jw, "defaultPos", el->defaultPos);
 	    jsonWriteNumber(jw, "orderKey", el->orderKey);
 	    jsonWriteObjectEnd(jw);
 	    }
 	jsonWriteObjectEnd(jw);
 	apiFinishOutput(0, NULL, jw);
 	}
     }
 else if (sameWord("tracks", words[1]))
     {
     char *extraArgs = verifyLegalArgs(argListTracks);
@@ -1173,31 +1173,31 @@
 	return;
 	}
     if (isEmpty(genome) || isEmpty(hubUrl))
 	{
         if (isEmpty(genome))
 	    apiErrAbort(err400, err400Msg, "must supply genome='someName' the name of a genome in a hub for /list/tracks\n");
 	if (isEmpty(hubUrl))
             apiErrAbort(err400, err400Msg, "must supply hubUrl='http:...' some URL to a hub for /list/tracks");
 	}
     struct trackHub *hub = errCatchTrackHubOpen(hubUrl);
     struct trackHubGenome *hubGenome = findHubGenome(hub, genome,
 	"/list/tracks", hubUrl);
     struct trackDb *tdbList = obtainTdb(hubGenome, NULL);
     struct jsonWrite *jw = apiStartOutput();
     jsonWriteString(jw, "hubUrl", hubUrl);
-    jsonWriteObjectStart(jw, hubGenome->name);
+    jsonWriteObjectStart(jw, trackHubSkipHubName(hubGenome->name));
     struct trackDb *el = NULL;
     for (el = tdbList; el != NULL; el = el->next )
 	    {
 	    recursiveTrackList(jw, el, db);
 	    }
     jsonWriteObjectEnd(jw);
     apiFinishOutput(0, NULL, jw);
     }
 else if (sameWord("chromosomes", words[1]))
     {
     char *extraArgs = verifyLegalArgs(argListChromosomes);
     if (extraArgs)
 	apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/chromosomes '%s'", extraArgs);
 
     char *hubUrl = cgiOptionalString("hubUrl");