a71215bcc4a26e1641770d82127dc57ced1842c8
braney
  Tue Mar 10 12:37:04 2026 -0700
Detect tracks that list themselves as their own parent, preventing infinite loop refs #35986

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

diff --git src/hg/lib/trackHub.c src/hg/lib/trackHub.c
index 4be26e187de..39154c1d327 100644
--- src/hg/lib/trackHub.c
+++ src/hg/lib/trackHub.c
@@ -1068,30 +1068,33 @@
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
     {
     char *parentLine = trackDbLocalSetting(tdb, "parent");
 
     // maybe it's a child of a supertrack?
     if (parentLine == NULL)
 	{
 	parentLine = trackDbLocalSetting(tdb, "superTrack");
 	if ((parentLine != NULL) && startsWith("on", parentLine))
 	    parentLine = NULL;
 	}
 
     if (parentLine != NULL)
          {
 	 char *parentName = cloneFirstWord(parentLine);
+	 if (sameString(parentName, tdb->track))
+	    errAbort("Track %s lists itself as its own parent in hub %s genome %s", tdb->track,
+		hub->url, genome->name);
 	 struct trackDb *parent = hashFindVal(hash, parentName);
 	 if (parent == NULL)
 	    errAbort("Parent %s of track %s doesn't exist in hub %s genome %s", parentName,
 		tdb->track, hub->url, genome->name);
 	 // mark the parent as a container
 	 parent->subtracks = tdb;
 
 	 // ugh...do this so requiredSetting looks at parent
 	 // in the case of views.  We clear this after 
 	 // validating anyway
 	 tdb->parent = parent;
 
 	 freeMem(parentName);
 	 }
     }