From cea0a647cf1f77f9efaafc64c230e5070ffea616 Mon Sep 17 00:00:00 2001 From: Nathan Wallace Date: Mon, 17 Nov 2025 03:57:59 -0500 Subject: [PATCH] Nil GlobalConfig causes panic in newRefreshConnectionState closes #4779 (#4899) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add test demonstrating nil GlobalConfig panic in newRefreshConnectionState Test: TestRefreshConnectionState_ConnectionOrderEdgeCases Demonstrates issue #4779 where nil GlobalConfig causes panic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * Add nil check for GlobalConfig in newRefreshConnectionState Fixes #4779: nil GlobalConfig causes panic in newRefreshConnectionState Changes: - Add nil check for GlobalConfig in newRefreshConnectionState before SetUserSearchPath - Add nil check in getDefaultSearchPath to handle nil GlobalConfig gracefully - Test now passes instead of panicking with nil pointer dereference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- pkg/connection/refresh_connections_state.go | 6 +++ .../refresh_connections_state_test.go | 37 +++++++++++++++++++ pkg/db/db_local/search_path.go | 10 +++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/pkg/connection/refresh_connections_state.go b/pkg/connection/refresh_connections_state.go index 0b7afc9c2..36a227de5 100644 --- a/pkg/connection/refresh_connections_state.go +++ b/pkg/connection/refresh_connections_state.go @@ -66,6 +66,12 @@ func newRefreshConnectionState(ctx context.Context, pluginManager pluginManager, if pool == nil { return nil, sperr.New("plugin manager returned nil pool") } + + // Check if GlobalConfig is initialized before proceeding + if steampipeconfig.GlobalConfig == nil { + return nil, sperr.New("GlobalConfig is not initialized") + } + // set user search path first log.Printf("[INFO] setting up search path") searchPath, err := db_local.SetUserSearchPath(ctx, pool) diff --git a/pkg/connection/refresh_connections_state_test.go b/pkg/connection/refresh_connections_state_test.go index 977a64ec7..76d81bb95 100644 --- a/pkg/connection/refresh_connections_state_test.go +++ b/pkg/connection/refresh_connections_state_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" "testing" "time" @@ -543,3 +544,39 @@ func TestNewRefreshConnectionState_NilPool(t *testing.T) { t.Error("Expected error when pool is nil, got nil") } } + +// TestRefreshConnectionState_ConnectionOrderEdgeCases tests edge cases in connection ordering +// This test demonstrates issue #4779 - nil GlobalConfig causes panic in newRefreshConnectionState +func TestRefreshConnectionState_ConnectionOrderEdgeCases(t *testing.T) { + t.Run("nil_global_config", func(t *testing.T) { + // ARRANGE: Save original GlobalConfig and set it to nil + originalConfig := steampipeconfig.GlobalConfig + steampipeconfig.GlobalConfig = nil + defer func() { + steampipeconfig.GlobalConfig = originalConfig + }() + + ctx := context.Background() + + // Create a mock plugin manager with a valid pool + // We need a pool to get past the nil pool check + // For this test, we can use a nil pool since we expect the function to fail + // before it tries to use the pool + mockPM := &mockPluginManager{ + pool: &pgxpool.Pool{}, // Need a non-nil pool to get past line 66-68 + } + + // ACT: Call newRefreshConnectionState with nil GlobalConfig + // This should not panic - should return an error instead + _, err := newRefreshConnectionState(ctx, mockPM, nil) + + // ASSERT: Should return an error, not panic + if err == nil { + t.Error("Expected error when GlobalConfig is nil, got nil") + } + + if err != nil && !strings.Contains(err.Error(), "GlobalConfig") { + t.Errorf("Expected error message to mention GlobalConfig, got: %v", err) + } + }) +} diff --git a/pkg/db/db_local/search_path.go b/pkg/db/db_local/search_path.go index 276037fbe..77c484134 100644 --- a/pkg/db/db_local/search_path.go +++ b/pkg/db/db_local/search_path.go @@ -81,9 +81,13 @@ func SetUserSearchPath(ctx context.Context, pool *pgxpool.Pool) ([]string, error func getDefaultSearchPath() []string { // add all connections to the seatrch path (UNLESS ImportSchema is disabled) var searchPath []string - for connectionName, connection := range steampipeconfig.GlobalConfig.Connections { - if connection.ImportSchema == modconfig.ImportSchemaEnabled { - searchPath = append(searchPath, connectionName) + + // Check if GlobalConfig is initialized + if steampipeconfig.GlobalConfig != nil { + for connectionName, connection := range steampipeconfig.GlobalConfig.Connections { + if connection.ImportSchema == modconfig.ImportSchemaEnabled { + searchPath = append(searchPath, connectionName) + } } }