{"record":{"id":"2a9f96cb1363c4be","repo":"Billionmail/BillionMail","slug":"database-connection-test-failed-after-10-attempts","errorCode":null,"errorMessage":"database connection test failed after 10 attempts","messagePattern":"database connection test failed after 10 attempts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/internal/service/database_initialization/database_initialization.go","lineNumber":61,"sourceCode":"\t// Testing database connection until successful\n\tconnectionOK := false\n\tfor i := 0; i < 10; i++ {\n\t\t_, err = g.DB().Exec(context.Background(), \"SELECT 1\")\n\n\t\tif err != nil {\n\t\t\t// Wait for 5 seconds before retrying\n\t\t\tg.Log().Debug(context.Background(), \"Database connection failed, retrying in 5 seconds...\")\n\t\t\ttime.Sleep(time.Second * 5)\n\t\t\tcontinue\n\t\t}\n\n\t\tconnectionOK = true\n\t\tg.Log().Debug(context.Background(), \"Database connection successful\")\n\t\tbreak\n\t}\n\n\tif !connectionOK {\n\t\treturn fmt.Errorf(\"database connection test failed after 10 attempts\")\n\t}\n\n\t// Execute registered handlers\n\tfor _, handler := range registeredHandlers {\n\t\tif handler != nil {\n\t\t\thandler()\n\t\t}\n\t}\n\n\t// Empty the registered handlers\n\tregisteredHandlers = registeredHandlers[:0]\n\n\treturn nil\n}\n\n// registerHandler registers a handler for the database initialization\nfunc registerHandler(handler func()) {\n\tif handler == nil {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/database_initialization/database_initialization.go#L43-L79","documentation":"After SetConfig, InitDatabase probes the DB by running SELECT 1 up to 10 times. If none of the 10 attempts succeed, it concludes the database is unreachable and returns this fixed error instead of the last driver error.","triggerScenarios":"PostgreSQL container not yet listening on its port within the ~10-retry window; wrong DBHOST/DBPORT; wrong credentials; DB volume uninitialized so postgres keeps restarting.","commonSituations":"First boot where the app starts before postgres is healthy (missing depends_on/healthcheck); credentials mismatch after changing DBPASS; network misconfiguration between containers; postgres crash-looping.","solutions":["Add a healthcheck + depends_on condition so the app waits for postgres before InitDatabase runs","Verify DBHOST/DBPORT/DBUSER/DBPASS match the postgres container's settings","Check postgres container logs for startup/auth errors (docker logs postgres)","Increase retry count/backoff if the DB legitimately takes longer than 10 attempts to become ready"],"exampleFix":"// before (docker-compose.yml)\napp:\n  depends_on: [postgres]\n// after\napp:\n  depends_on:\n    postgres:\n      condition: service_healthy","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", net.JoinHostPort(dbHost, dbPort), 3*time.Second)\nif err != nil { return fmt.Errorf(\"postgres not reachable yet: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err := database_initialization.InitDatabase(); err != nil {\n    if strings.Contains(err.Error(), \"connection test failed after 10 attempts\") {\n        // back off and retry whole init\n        time.Sleep(10 * time.Second)\n        return retryInit()\n    }\n}","preventionTips":["Use depends_on with service_healthy for postgres","Add exponential backoff instead of fixed 10 tries","Alert on postgres crash-looping before app starts","Verify credentials with a psql smoke test"],"tags":["database","connectivity","startup"],"backgroundTag":"database-connection-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}