3a52ad30839586e54377927d8ee87a65d4806a7f
galt
  Thu Oct 23 21:21:22 2025 -0700
hubCheck can now scan for and report with text valid values for VIEWLIMIT VIEWLIMITMAX and DEFAULTVIEWLIMIT. fixes #12098

diff --git src/hg/lib/wiggleCart.c src/hg/lib/wiggleCart.c
index f884491b2bf..9eff4e7cc3c 100644
--- src/hg/lib/wiggleCart.c
+++ src/hg/lib/wiggleCart.c
@@ -62,89 +62,89 @@
     else
 	fprintf( dF, "%s:\n", name);
     }
     dbgMsg[0] = (char) NULL;
     fflush(dF);
 }
 
 #ifdef NOT
 /*	example usage:	*/
 safef(dbgMsg, DBGMSGSZ, "%s pixels: min,default,max: %d:%d:%d", tdb->track, wigCart->minHeight, wigCart->defaultHeight, wigCart->maxHeight);
 wigDebugPrint("wigFetch");
 #endif
 
 #endif
 
-static void parseColonRange(char *setting, double *retMin, double *retMax)
+static void parseColonRange(char *settingName, char *setting, double *retMin, double *retMax)
 /* Parse setting's two colon-separated numbers into ret{Min,Max}, unless setting
  * is NULL or empty or retMin/retMax is NULL.  errAbort if invalid format. */
 {
 if (isNotEmpty(setting))
     {
     char tmp[64]; // Intentionally small -- should be only 2 floating point #s + ':'
     safecpy(tmp, sizeof(tmp), setting);
     char *words[3];
     if (chopByChar(tmp, ':', words, ArraySize(words)) == 2)
         {
 	double low = sqlDouble(words[0]);
         double high = sqlDouble(words[1]);
         correctOrder(low, high);
 	if (retMin)
 	    *retMin = low;
 	if (retMax)
 	    *retMax = high;
         }
     else
-	errAbort("Can't parse colon range '%s'", setting);
+	errAbort("Can't parse colon range value '%s' in setting %s", setting, settingName);
     }
 }
 
 static void viewLimitsCompositeOverride(struct trackDb *tdb,char *name, double *retMin,
                                         double *retMax,double *absMin, double *absMax)
 /* If aquiring min/max for composite level wig cfg. Look in parents as well as self. */
 {
 if (isNameAtParentLevel(tdb,name))
     {
     char *setting = NULL;
     if (absMin != NULL && absMax != NULL)
         {
         setting = trackDbSettingByView(tdb,MIN_LIMIT);
         if (setting != NULL)
             {
             if (setting[0] != '\0')
                 *absMin = sqlDouble(setting);
             }
         setting = trackDbSettingByView(tdb,MAX_LIMIT);
         if (setting != NULL)
             {
             if (setting[0] != '\0')
                 *absMax = sqlDouble(setting);
             }
         else
             {
             setting = trackDbSettingByView(tdb,VIEWLIMITSMAX);  // Legacy
             if (setting != NULL)
                 {
-                parseColonRange(setting, absMin, absMax);
+                parseColonRange(VIEWLIMITSMAX, setting, absMin, absMax);
                 }
             }
         }
 
     setting = trackDbSettingByView(tdb, VIEWLIMITS);
     if (setting != NULL)
         {
-        parseColonRange(setting, retMin, retMax);
+        parseColonRange(VIEWLIMITS, setting, retMin, retMax);
         }
     }
 }
 
 void wigFetchMinMaxYWithCart(struct cart *theCart, struct trackDb *tdb, char *name,
                              double *retMin, double *retMax, double *retAbsMin, double *retAbsMax,
                              int wordCount, char **words)
 /*****************************************************************************
  *	Min, Max Y viewing limits
  *	Absolute limits are defined on the trackDb type line for wiggle,
  *	or MIN_LIMIT / MAX_LIMIT trackDb settings for bedGraph
  *	User requested limits are defined in the cart
  *	Default opening display limits are optionally defined with the
  *		defaultViewLimits or viewLimits declaration from trackDb
  *****************************************************************************/
@@ -194,36 +194,40 @@
 if(cartMinStr)
     *retMin = atof(cartMinStr);
 if(cartMaxStr)
     *retMax = atof(cartMaxStr);
 if (cartMinStr && cartMaxStr)
     correctOrder(*retMin, *retMax);
 // If it weren't for the the allowance for missing data range values,
 // we could set retAbs* and be done here.
 if(cartMinStr)
     cartMin = *retMin;
 if(cartMaxStr)
     cartMax = *retMax;
 
 // Get trackDb defaults, and resolve missing wiggle data range if necessary.
 char *defaultViewLimits = trackDbSettingClosestToHomeOrDefault(tdb, DEFAULTVIEWLIMITS, NULL);
+char *defaultViewLimitsName = DEFAULTVIEWLIMITS;
 if (defaultViewLimits == NULL)
+    {
     defaultViewLimits = trackDbSettingClosestToHomeOrDefault(tdb, VIEWLIMITS, NULL);
+    defaultViewLimitsName = VIEWLIMITS;
+    }
 if (defaultViewLimits != NULL)
     {
     double viewLimitMin = 0.0, viewLimitMax = 0.0;
-    parseColonRange(defaultViewLimits, &viewLimitMin, &viewLimitMax);
+    parseColonRange(defaultViewLimitsName, defaultViewLimits, &viewLimitMin, &viewLimitMax);
     *retMin = viewLimitMin;
     *retMax = viewLimitMax;
     if (missingAbsMax)
 	absMax = viewLimitMax;
     if (missingAbsMin)
 	absMin = viewLimitMin;
     }
 else if (missingAbsMin || missingAbsMax)
     {
     if (isBedGraph)
 	{
 	absMin = DEFAULT_MIN_BED_GRAPH;
 	absMax = DEFAULT_MAX_BED_GRAPH;
 	}
     else