From 5d879ffeb801bc3dce1c1f6fef4cd414e96d9ab0 Mon Sep 17 00:00:00 2001 From: Gregory Newman-Smith Date: Tue, 18 Nov 2025 13:32:47 +0000 Subject: [PATCH 1/2] CBG-4981: fix panic in _config?include_runtime=true endpoint --- rest/admin_api.go | 16 +++++++++------- rest/api_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/rest/admin_api.go b/rest/admin_api.go index 8e841f0608..d4be499190 100644 --- a/rest/admin_api.go +++ b/rest/admin_api.go @@ -512,15 +512,17 @@ func (h *handler) handleGetConfig() error { return err } - replications, err := database.SGReplicateMgr.GetReplications() - if err != nil { - return err - } + if database.SGReplicateMgr != nil { + replications, err := database.SGReplicateMgr.GetReplications() + if err != nil { + return err + } - dbConfig.Replications = make(map[string]*db.ReplicationConfig, len(replications)) + dbConfig.Replications = make(map[string]*db.ReplicationConfig, len(replications)) - for replicationName, replicationConfig := range replications { - dbConfig.Replications[replicationName] = replicationConfig.ReplicationConfig.Redacted(h.ctx()) + for replicationName, replicationConfig := range replications { + dbConfig.Replications[replicationName] = replicationConfig.ReplicationConfig.Redacted(h.ctx()) + } } } diff --git a/rest/api_test.go b/rest/api_test.go index 7c463f3aa8..660dc06454 100644 --- a/rest/api_test.go +++ b/rest/api_test.go @@ -28,6 +28,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "testing" "time" @@ -3710,3 +3711,37 @@ func TestUnsupportedServerConfigOptions(t *testing.T) { }) } } + +func TestGetConfigAfterFailToStartOnlineProcess(t *testing.T) { + rt := NewRestTester(t, &RestTesterConfig{ + PersistentConfig: true, + }) + defer rt.Close() + + dbConfig := rt.NewDbConfig() + dbConfig.StartOffline = base.Ptr(true) + resp := rt.CreateDatabase("db", dbConfig) + RequireStatus(t, resp, http.StatusCreated) + + // create invalid user to cause StartOnlineProcesses error + rt.GetDatabase().Options.ConfigPrincipals.Users = map[string]*auth.PrincipalConfig{ + "alice": { + JWTChannels: base.SetOf("asdf"), + }, + } + + // simulate regular startup + atomic.StoreUint32(&rt.GetDatabase().State, db.DBStarting) + rt.WaitForDBState(db.RunStateString[db.DBStarting]) + + // Can't trigger error case from REST API - call directly + rt.ServerContext().asyncDatabaseOnline(base.NewNonCancelCtx(), rt.GetDatabase(), nil, rt.ServerContext().GetDbVersion("db")) + + // Error should cause db to stay offline. + rt.WaitForDBState(db.RunStateString[db.DBOffline]) + require.Equal(t, int64(1), rt.GetDatabase().DbStats.Database().TotalOnlineFatalErrors.Value()) + + // Original bug will trigger panic here on this endpoint + resp = rt.SendAdminRequest(http.MethodGet, "/_config?include_runtime=true", "") + RequireStatus(t, resp, http.StatusOK) +} From 73dbe946a09d5acbfd727ecb767f0f0c74d96e24 Mon Sep 17 00:00:00 2001 From: Gregory Newman-Smith Date: Tue, 18 Nov 2025 13:38:34 +0000 Subject: [PATCH 2/2] update comments --- rest/api_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rest/api_test.go b/rest/api_test.go index 660dc06454..8321fd8cc3 100644 --- a/rest/api_test.go +++ b/rest/api_test.go @@ -3730,7 +3730,9 @@ func TestGetConfigAfterFailToStartOnlineProcess(t *testing.T) { }, } - // simulate regular startup + // Directly set the database state to DBStarting to simulate regular startup. + // This direct atomic manipulation is required in this test to simulate a state transition. + // This is safe in the context of this test. atomic.StoreUint32(&rt.GetDatabase().State, db.DBStarting) rt.WaitForDBState(db.RunStateString[db.DBStarting])