{"record":{"id":"0837197c68953fc7","repo":"charmbracelet/crush","slug":"failed-to-detach-crush-server-process-v","errorCode":null,"errorMessage":"failed to detach crush server process: %v","messagePattern":"failed to detach crush server process: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/root.go","lineNumber":899,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create stdout log file: %v\", err)\n\t}\n\tdefer stdout.Close()\n\tc.Stdout = stdout\n\n\tstderr, err := os.Create(stderrPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create stderr log file: %v\", err)\n\t}\n\tdefer stderr.Close()\n\tc.Stderr = stderr\n\n\tif err := c.Start(); err != nil {\n\t\treturn fmt.Errorf(\"failed to start crush server: %v\", err)\n\t}\n\n\tif err := c.Process.Release(); err != nil {\n\t\treturn fmt.Errorf(\"failed to detach crush server process: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc shouldEnableMetrics(cfg *config.Config) bool {\n\tif v, _ := strconv.ParseBool(os.Getenv(\"CRUSH_DISABLE_METRICS\")); v {\n\t\treturn false\n\t}\n\tif v, _ := strconv.ParseBool(os.Getenv(\"DO_NOT_TRACK\")); v {\n\t\treturn false\n\t}\n\tif cfg.Options.DisableMetrics {\n\t\treturn false\n\t}\n\treturn true\n}\n","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/root.go#L881-L917","documentation":"Wraps the error from os/exec's Process.Release() after successfully starting the detached server. Release detaches the parent from the child so it won't be reaped; failure usually means the child already exited and was reaped, or the process handle is invalid on this platform.","triggerScenarios":"startDetachedServer calls c.Process.Release() after c.Start(); the child exited immediately after start (crash, port conflict, bad config), or the OS already reaped it, making the handle stale.","commonSituations":"Server crashes on startup so the process is gone by Release time; sandboxed environments limiting process APIs; race between a supervisor and Release.","solutions":["Check the server's stderr log file for the real startup failure before Release","Verify server port/config so the child survives long enough to be released","Treat Release failure as non-fatal if the readiness probe confirms the server is healthy","Retry spawnAndWaitReady once, since the failure can be a transient reaping race"],"exampleFix":"// before: abort on any Release error\nif err := c.Process.Release(); err != nil {\n\treturn fmt.Errorf(\"failed to detach crush server process: %v\", err)\n}\n// after: log but continue if readiness probe succeeds\nif err := c.Process.Release(); err != nil {\n\tslog.Warn(\"Failed to detach crush server process\", \"error\", err)\n}","handlingStrategy":"try-catch","validationCode":"// No practical pre-call validation; verify child health around Release.\nready := waitForServerReady(addr, 5*time.Second)","typeGuard":null,"tryCatchPattern":"if err := startDetachedServer(cmd); err != nil {\n\tif strings.Contains(err.Error(), \"detach\") && isServerHealthy(addr) {\n\t\tslog.Warn(\"Detach failed but server is healthy; continuing\")\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Pair Release with a readiness probe so a failed release of a dead child is caught","Inspect the child's stderr log when Release fails","Avoid double-spawning supervisors that race on reaping","Keep Go and the execution environment updated (platform Release quirks)"],"tags":["process-spawn","detach","go"],"backgroundTag":"process-release-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}