{"record":{"id":"4b9258abd8938342","repo":"gastownhall/beads","slug":"server-doltserver-start-w","errorCode":null,"errorMessage":"server: DoltServer.Start: %w","messagePattern":"server: DoltServer\\.Start: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/server/doltserver.go","lineNumber":314,"sourceCode":"\t\t_ = cmd.Process.Kill()\n\t\t_, _ = cmd.Process.Wait()\n\t\ts.eg, s.egCtx, s.cancel, s.pid = nil, nil, nil, 0\n\t\tcancel()\n\t\tlock.Unlock()\n\t\treturn fmt.Errorf(\"server: DoltServer.Start: write pidfile: %w\", err)\n\t}\n\n\teg.Go(func() error {\n\t\tdefer lock.Unlock()\n\t\treturn cmd.Wait()\n\t})\n\n\tif err := s.waitReady(ctx); err != nil {\n\t\tcancel()\n\t\t_ = s.eg.Wait()\n\t\ts.eg, s.egCtx, s.cancel, s.pid = nil, nil, nil, 0\n\t\t_ = pidfile.Remove(s.rootDir, PIDFileName)\n\t\treturn fmt.Errorf(\"server: DoltServer.Start: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (s *DoltServer) waitReady(ctx context.Context) error {\n\tdeadline := time.Now().Add(startReadyTimeout)\n\tfor {\n\t\tif s.egCtx.Err() != nil {\n\t\t\treturn errors.New(\"dolt sql-server exited before listener became ready\")\n\t\t}\n\n\t\tdctx, dcancel := context.WithTimeout(ctx, startReadyDialTimeout)\n\t\tconn, err := s.Dial(dctx)\n\t\tdcancel()\n\t\tif err == nil {\n\t\t\t_ = conn.Close()\n\t\t\treturn nil\n\t\t}","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/server/doltserver.go#L296-L332","documentation":"Generic wrapper: Start() got past spawning and the pidfile, but waitReady() failed — the dolt sql-server never became dialable within the 30s ready timeout (or its errgroup died, or the caller's ctx was cancelled). The child is stopped, the errgroup drained, and the pidfile removed before returning.","triggerScenarios":"waitReady returns any error: listener never accepts a TCP/socket connection within startReadyTimeout (30s), dolt exited before binding, or the ctx passed to Start() was cancelled. Includes wrapped errors 2406 and the internal \"dolt sql-server exited before listener became ready\".","commonSituations":"Slow cold start on loaded machines exceeding 30s; dolt crashing at boot due to bad config (check the log file); port conflicts or host binding misconfiguration; NFS-mounted data dir where the listener comes up late.","solutions":["Read the server log file passed to NewDoltServer — dolt's own startup error (bad config, port in use) is written there.","Verify the configured host/port in the dolt server YAML is free: `ss -ltnp | grep <port>`.","Increase readiness headroom by reducing machine load or moving the data dir off slow network storage; ensure Start's ctx is not cancelled early.","Run `dolt sql-server --config <configPath>` manually in rootDir to reproduce and see the startup error directly."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 5*time.Second)\ndefer cancel()\nerr := srv.Start(ctx) // ctx cancels before listener is ready\n// after\nstartCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second)\ndefer cancel()\nerr := srv.Start(startCtx)","handlingStrategy":"try-catch","validationCode":"// Sanity-check config and that the configured port is free before Start.\nif cfgPort := configuredPort(configPath); cfgPort != 0 {\n    ln, err := net.Listen(\"tcp\", fmt.Sprintf(\"%s:%d\", configuredHost(configPath), cfgPort))\n    if err != nil {\n        return fmt.Errorf(\"configured port %d unavailable: %w\", cfgPort, err)\n    }\n    ln.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := srv.Start(ctx); err != nil {\n    var detail string\n    if strings.Contains(err.Error(), \"listener not ready\") {\n        detail = \"dolt did not become ready in time; check server log for child crash\"\n    } else if strings.Contains(err.Error(), \"exited before listener\") {\n        detail = \"dolt crashed at startup; check server log\"\n    }\n    return fmt.Errorf(\"%s: %w\", detail, err)\n}","preventionTips":["Always pass a context to Start with a generous timeout (>= 30s ready window).","Configure a log file so child startup failures are visible.","Pre-check that the configured host/port is bindable.","Keep the data dir on fast local storage to stay under the 30s readiness window."],"tags":["startup","timeout","process-management"],"backgroundTag":"server-startup-timeout","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}