1948a03c367e4a9686f0bda2a6427859e3f4138a
hiram
  Wed Jul 1 12:10:01 2026 -0700
do not talk to ottoTable until you really need to do that - patch fix for v500 refs #37839

diff --git src/hg/hubApi/liftOver.c src/hg/hubApi/liftOver.c
index 3c655490ab1..857cb585157 100644
--- src/hg/hubApi/liftOver.c
+++ src/hg/hubApi/liftOver.c
@@ -63,31 +63,31 @@
     jsonWriteString(jw, NULL, position);
     jsonWriteString(jw, NULL, coverage);
     jsonWriteListEnd(jw);
     }
 jsonWriteListEnd(jw);
 apiFinishOutput(0, NULL, jw);
 }
 
 static void listExisting()
 /* output the fromDb,toDb from liftOverChain.hgcentral SQL table */
 {
 char *filter = cgiOptionalString(argFilter);
 char *fromDb = cgiOptionalString(argFromGenome);
 char *toDb = cgiOptionalString(argToGenome);
 
-struct sqlConnection *conn = hConnectOtto();
+struct sqlConnection *conn = hConnectCentral();
 char *tableName = cloneString(liftOverChainTable());
 struct dyString *query = newDyString(0);
 sqlDyStringPrintf(query, "SELECT count(*) FROM %s", tableName);
 long long totalRows = sqlQuickLongLong(conn, dyStringContents(query));
 dyStringClear(query);
 
 if (isNotEmpty(fromDb) && isNotEmpty(toDb))
     {
     /* match a chain recorded in either direction */
     sqlDyStringPrintf(query, "SELECT * FROM %s WHERE "
         "(LOWER(fromDb) = LOWER('%s') AND LOWER(toDb) = LOWER('%s')) "
         "OR (LOWER(fromDb) = LOWER('%s') AND LOWER(toDb) = LOWER('%s'))",
         tableName, fromDb, toDb, toDb, fromDb);
     }
 else if (isNotEmpty(fromDb) || isNotEmpty(toDb))
@@ -131,53 +131,55 @@
     jsonWriteString(jw, "fudgeThick", chain->fudgeThick);
     jsonWriteObjectEnd(jw);
     }
 jsonWriteListEnd(jw);
 jsonWriteNumber(jw, "totalLiftOvers", totalRows);
 int chainListCount = slCount(chainList);
 jsonWriteNumber(jw, "itemsReturned", chainListCount);
 liftOverChainFreeList(&chainList);
 
 /* if no chain rows for this pair, check ottoRequest for any existing
  * row (any status) so the user is told their pair has already been
  * submitted instead of being allowed to create a duplicate row */
 if (chainListCount == 0 && isNotEmpty(fromDb) && isNotEmpty(toDb))
     {
     char *ottoTable = cfgOption("ottoTable");
-    if (isNotEmpty(ottoTable) && sqlTableExists(conn, ottoTable))
+    struct sqlConnection *ottoConn = hConnectOtto();
+    if (isNotEmpty(ottoTable) && sqlTableExists(ottoConn, ottoTable))
         {
         struct dyString *pq = newDyString(0);
         sqlDyStringPrintf(pq,
             "SELECT id, status, requestTime FROM %s "
             "WHERE requestType='liftOver' AND "
             "((fromDb='%s' AND toDb='%s') OR (fromDb='%s' AND toDb='%s')) "
             "ORDER BY requestTime DESC LIMIT 1",
             ottoTable, fromDb, toDb, toDb, fromDb);
         char **row;
-        struct sqlResult *sr = sqlGetResult(conn, dyStringCannibalize(&pq));
+        struct sqlResult *sr = sqlGetResult(ottoConn, dyStringCannibalize(&pq));
         if ((row = sqlNextRow(sr)) != NULL)
             {
             jsonWriteBoolean(jw, "pending", TRUE);
             jsonWriteNumber(jw, "pendingStatus", sqlSigned(row[1]));
             jsonWriteString(jw, "pendingRequestTime", row[2]);
             }
         sqlFreeResult(&sr);
         }
+    hDisconnectOtto(&ottoConn);
     }
 
 apiFinishOutput(0, NULL, jw);
-hDisconnectOtto(&conn);
+hDisconnectCentral(&conn);
 }
 
 static void loginStatus()
 /* output current user login status as JSON */
 {
 /* wikiLinkUserName() handles all cookie validation internally */
 char *userName = wikiLinkUserName();
 struct jsonWrite *jw = apiStartOutput();
 char hgLoginLink[2048];
 boolean privateHost = hIsPrivateHost();
 /* can not use hgcentral hglogin from hgwdev/genome-test */
 if (privateHost)
     safef(hgLoginLink, sizeof(hgLoginLink), "%shgLogin", hLocalHostCgiBinUrl());
 else
     safef(hgLoginLink, sizeof(hgLoginLink), "%shgLogin", hLoginHostCgiBinUrl());