{"record":{"id":"27fae8cf7a6c7076","repo":"argoproj/argo-workflows","slug":"failed-to-create-initial-database-session-w","errorCode":null,"errorMessage":"failed to create initial database session: %w","messagePattern":"failed to create initial database session: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"util/sqldb/session.go","lineNumber":121,"sourceCode":"\n\tif proxy.maxRetries == 0 {\n\t\tproxy.maxRetries = 5\n\t}\n\tif proxy.baseDelay == 0 {\n\t\tproxy.baseDelay = 100 * time.Millisecond\n\t}\n\tif proxy.maxDelay == 0 {\n\t\tproxy.maxDelay = 30 * time.Second\n\t}\n\n\t// just trying to account for float funkiness\n\t// a value between 0 and 1 is (almost) always non-sensical, but we allow it\n\tif proxy.retryMultiple <= 0.000000001 {\n\t\tproxy.retryMultiple = 1.0\n\t}\n\n\tif err := proxy.connect(ctx); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create initial database session: %w\", err)\n\t}\n\n\treturn proxy, nil\n}\n\n// NewSessionProxyFromSession creates a SessionProxy from an existing session with credentials\nfunc NewSessionProxyFromSession(sess db.Session, dbConfig *config.DBConfig, username, password string) *SessionProxy {\n\treturn &SessionProxy{\n\t\tsess:          sess,\n\t\tdbConfig:      dbConfig,\n\t\tusername:      username,\n\t\tpassword:      password,\n\t\tdbType:        dbTypeFromConfig(dbConfig),\n\t\tmaxRetries:    5,\n\t\tbaseDelay:     100 * time.Millisecond,\n\t\tmaxDelay:      30 * time.Second,\n\t\tretryMultiple: 2.0,\n\t}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/util/sqldb/session.go#L103-L139","documentation":"NewSessionProxy validates retry params, then calls proxy.connect(ctx) to establish the first database session; any failure there (auth selection failure, CreateDBSession error, Ping failure) is wrapped as \"failed to create initial database session\". Callers like Run, NewLockManager, and SessionProxyFromConfig receive this when the controller cannot establish its initial DB connection at startup.","triggerScenarios":"NewSessionProxy fails because connect() errors: neither kubectl-config/namespace nor username/password auth combos are satisfied (insufficient auth info), CreateDBSession/CreateDBSessionWithCreds fail (bad DSN, unreachable host, wrong credentials), or sess.Ping() fails.","commonSituations":"Database host misconfigured or down when the controller starts; wrong Postgres/MySQL credentials in the K8s secret; network policy/Security Group blocking port 5432/3306; the persistence config partially filled so no auth branch matches; DNS resolution failure in-cluster.","solutions":["Unwrap the %w cause to find the real failure (DSN error, connection refused, auth rejected, ping timeout).","Verify the DB host:port is reachable from the controller pod (kubectl exec + nc/psql test) and DNS resolves.","Check the K8s secret referenced by the persistence config contains correct username/password, or that direct username/password are both set.","Confirm persistence config completeness: either kubectlConfig+namespace+dbConfig or username+password+dbConfig must all be present.","If the DB was temporarily down, restart the controller after the database is healthy — this error occurs only at initial creation, before the reconnect logic is active."],"exampleFix":"// before (config missing credentials path)\npersistence: {postgresql: {host: pg}}  // no secret/username\n// after\npersistence:\n  postgresql:\n    host: pg\n    userNameSecret: {name: argo-pg-secret, key: username}\n    passwordSecret: {name: argo-pg-secret, key: password}","handlingStrategy":"try-catch","validationCode":"func cfgOK(c SessionProxyConfig) bool {\n    hasKube := c.KubectlConfig != nil && c.Namespace != \"\"\n    hasCreds := c.Username != \"\" && c.Password != \"\"\n    return (hasKube || hasCreds) && !reflect.DeepEqual(c.DBConfig, config.DBConfig{})\n}","typeGuard":null,"tryCatchPattern":"proxy, err := NewSessionProxy(ctx, cfg)\nif err != nil {\n    var outer = err\n    for unwrapped := errors.Unwrap(err); unwrapped != nil; unwrapped = errors.Unwrap(unwrapped) {\n        outer = unwrapped\n    }\n    log.Fatalf(\"initial DB session failed (cause: %v) — check DB host, creds, network\", outer)\n}","preventionTips":["Validate persistence config (secrets exist, host/port set) before controller start.","Monitor the DB itself with readiness probes so the controller starts after the DB.","Pre-flight test the DSN from inside the cluster network.","Log the unwrapped cause, not just the wrapper, in startup failure handlers."],"tags":["database","connection","startup","postgres","mysql"],"backgroundTag":"initial-db-connection-failed","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}