390ac49268af6881834e0b5eda1f7186814126cc
chmalee
  Thu Mar 6 10:31:39 2025 -0800
Check that subtracks have the same group setting as their parent track, refs #35078

diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c
index 77eabf40b7d..a173bb0c140 100644
--- src/hg/utils/hubCheck/hubCheck.c
+++ src/hg/utils/hubCheck/hubCheck.c
@@ -607,45 +607,55 @@
 }
 
 boolean checkEmptyMembersForAll(membersForAll_t *membersForAll, struct trackDb *parentTdb)
 /* membersForAll may be allocated and exist but not have any actual members defined. */
 {
 int i;
 for (i = 0; i < ArraySize(membersForAll->members); i++)
     {
     if (membersForAll->members[i] != NULL)
         return TRUE;
     }
 return FALSE;
 }
 
 int hubCheckSubtrackSettings(struct trackHubGenome *genome, struct trackDb *tdb, struct dyString *errors, struct trackHubCheckOptions *options)
-/* Check that 'subgroups' are consistent with what is defined at the parent level */
+/* Check subtrack specific settings, for example that 'subgroups' are consistent with what
+ * is defined at the parent level */
 {
 int retVal = 0;
 if (!tdbIsSubtrack(tdb))
     return retVal;
 
 int i;
 char *subtrackName = trackHubSkipHubName(tdb->track);
 sortOrder_t *sortOrder = NULL;
 membership_t *membership = NULL;
 membersForAll_t *membersForAll = NULL;
 struct errCatch *errCatch = errCatchNew();
 
 if (errCatchStart(errCatch))
     {
+    // check that subtrack group is the same as the parent group:
+    char *subTrackGroup = tdb->grp;
+    char *parentGroup = tdb->parent->grp;
+    if (!sameString(subTrackGroup, parentGroup))
+        {
+        errAbort("assembly %s: track %s has a different group (%s) than parent %s (group %s). Please specify the group setting in both the parent and the subtrack stanzas", trackHubSkipHubName(genome->name), subtrackName, subTrackGroup, trackHubSkipHubName(tdb->parent->track), parentGroup);
+        }
+
+    // check subgroups settings
     membersForAll = membersForAllSubGroupsGet(tdb->parent, NULL);
 
     // membersForAllSubGroupsGet() warns about the parent stanza, turn it into an errAbort
     if (errCatch->gotWarning)
         {
         errAbort("%s", errCatch->message->string);
         }
 
     if (membersForAll && checkEmptyMembersForAll(membersForAll, tdb->parent))
         {
         membership = subgroupMembershipGet(tdb);
         sortOrder = sortOrderGet(NULL, tdb->parent);
 
         if (membership == NULL)
             {