049e50b2293ce5e9102eef9177a7cb88b49d7a10
chmalee
  Wed Mar 4 14:14:03 2026 -0800
Move chromosome:start-end parsing into it's own function in hgFind so we can call just that code from elsewhere. Add a defaultPosition check for assembly hub into hubCheck that verifies the requested chromosome exists for that assembly. Do not warn if the range is too large since we actually silently accept that anyways and clamp to the chromosome ends. refs #37126

diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c
index 72fe62e50c0..977dd1c2f00 100644
--- src/hg/utils/hubCheck/hubCheck.c
+++ src/hg/utils/hubCheck/hubCheck.c
@@ -7,30 +7,31 @@
 #include "bigBed.h"
 #include "dystring.h"
 #include "errCatch.h"
 #include "hgBam.h"
 #include "htmshell.h"
 #include "htmlPage.h"
 #include "hui.h"
 #include "net.h"
 #include "options.h"
 #include "trackDb.h"
 #include "trackHub.h"
 #include "udc.h"
 #include "vcf.h"
 #include "bedTabix.h"
 #include "knetUdc.h"
+#include "hgFind.h"
 
 #ifdef USE_HAL
 #include "halBlockViz.h"
 #endif
 
 static int cacheTime = 1;
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "hubCheck - Check a track data hub for integrity.\n"
   "usage:\n"
   "   hubCheck http://yourHost/yourDir/hub.txt\n"
   "options:\n"
@@ -1070,41 +1071,55 @@
 struct errCatch *errCatch = errCatchNew();
 struct trackDb *tdbList = NULL;
 int genomeErrorCount = 0;
 boolean openedGenome = FALSE;
 verbose(3, "checking genome %s\n", trackHubSkipHubName(genome->name));
 
 if (errCatchStart(errCatch))
     {
     if (genome->twoBitPath != NULL)
         {
         // check that twoBitPath is a valid file, warn instead of errAbort so we can continue checking
         // the genome stanza
         char *twoBit = genome->twoBitPath;
         if (!extFileExists(twoBit))
             warn("Error: '%s' twoBitPath does not exist or is not accessible: '%s'", genome->name, twoBit);
+        else
+            {
+            // verify that the defaultPos references an actual chromosome and valid range for that chromosome
+            char *inpPos = cloneString(genome->defaultPos);
+            int relStart = 0, relEnd = 0;
+            boolean relativeFlag = FALSE, singleBaseSpec = FALSE;
+            if (!parseAndResolvePosition(&inpPos, genome->name, NULL, &relStart, &relEnd, &relativeFlag, &singleBaseSpec))
+                {
+                // again use a warn so we can continue checking other genome stanza settings that do not
+                // rely on the 2bit file
+                warn("Error: '%s' defaultPos '%s' does not reference a valid chromosome in the 2bit file: '%s'", trackHubSkipHubName(genome->name), genome->defaultPos, twoBit);
+                }
+            }
 
         // groups and htmlPath are optional settings, again only warn if they are malformed
         char *groupsFile = genome->groups;
         if (groupsFile != NULL && !extFileExists(groupsFile))
             warn("warning: '%s' groups file does not exist or is not accessible: '%s'", genome->name, groupsFile);
 
         char *htmlPath = hashFindVal(genome->settingsHash, "htmlPath");
         if (htmlPath == NULL)
             warn("warning: missing htmlPath setting for assembly hub '%s'", genome->name);
         else if (!extFileExists(htmlPath))
             warn("warning: '%s' htmlPath file does not exist or is not accessible: '%s'", genome->name, htmlPath);
+
         }
     boolean foundFirstGenome = FALSE;
     tdbList = trackHubTracksForGenome(hub, genome, NULL, &foundFirstGenome);
     tdbList = trackDbLinkUpGenerations(tdbList);
     tdbList = trackDbPolishAfterLinkup(tdbList, genome->name);
     trackHubPolishTrackNames(hub, tdbList);
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError || errCatch->gotWarning)
     {
     openedGenome = TRUE;
     genomeErr(errors, errCatch->message->string, hub, genome, options->htmlOut);
     if (errCatch->gotError || !options->allowWarnings)
         genomeErrorCount += 1;
     }