{"record":{"id":"b569fac865628c24","repo":"charmbracelet/crush","slug":"failed-to-get-executable-path-v","errorCode":null,"errorMessage":"failed to get executable path: %v","messagePattern":"failed to get executable path: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/root.go","lineNumber":858,"sourceCode":"\t\tif _, err := os.Stat(hostURL.Host); errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn nil\n\t\t}\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-time.After(100 * time.Millisecond):\n\t\t}\n\t}\n\t_ = os.Remove(hostURL.Host)\n\treturn nil\n}\n\nvar safeNameRegexp = regexp.MustCompile(`[^a-zA-Z0-9._-]`)\n\nfunc startDetachedServer(cmd *cobra.Command, hostURL *url.URL) error {\n\texe, err := os.Executable()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get executable path: %v\", err)\n\t}\n\n\tchDir, err := perHostServerDir(hostURL)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcmdArgs := []string{\"server\"}\n\tif clientHost != server.DefaultHost() {\n\t\tcmdArgs = append(cmdArgs, \"--host\", clientHost)\n\t}\n\n\t// Use context.Background() so the parent's context cancellation does not\n\t// kill the spawned server. detachProcess (Setsid on !windows,\n\t// DETACHED_PROCESS on windows) is what truly detaches the child from\n\t// this process's lifetime.\n\tc := exec.CommandContext(context.Background(), exe, cmdArgs...)\n\tstdoutPath := filepath.Join(chDir, \"stdout.log\")","sourceCodeStart":840,"sourceCodeEnd":876,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/root.go#L840-L876","documentation":"startDetachedServer calls os.Executable() to locate the current binary so it can re-exec itself as the detached server process. If the OS cannot resolve the executable path, the error is wrapped as 'failed to get executable path' and server startup aborts.","triggerScenarios":"os.Executable fails with a kernel/OS error: the binary was deleted or replaced while running (Linux returns ENOENT in some delete/rename races), or an exotic exec environment where /proc mappings are unavailable.","commonSituations":"Upgrading crush (deleting/replacing the binary) while a client is starting a server; running from a tmpfs that was cleaned; executing via wrappers that confuse path resolution; deleted binaries in /tmp.","solutions":["Re-run crush from a stable, installed binary (not a deleted or tmp-resident one).","Avoid replacing/renaming the executable while crush is starting; finish upgrades, then restart.","Install the binary in a standard location on a persistent filesystem instead of /tmp or a RAM disk."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"exe, err := os.Executable()\nif err != nil {\n\treturn fmt.Errorf(\"cannot locate executable: %w\", err)\n}\nif _, err := os.Stat(exe); err != nil {\n\treturn fmt.Errorf(\"executable missing on disk: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never delete or rename the binary while a crush client may spawn a server","Install crush in a stable location, not /tmp or ephemeral storage","Complete upgrades atomically (write new file, rename) and restart clients afterwards","Re-launch crush from a fresh shell after upgrading"],"tags":["executable","process-spawn","server","os"],"backgroundTag":"executable-path-resolution-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}