{"record":{"id":"191bca75d4951a2b","repo":"valyala/fasthttp","slug":"prefork-start-child-q-w","errorCode":null,"errorMessage":"prefork: start child %q: %w","messagePattern":"prefork: start child %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"prefork/prefork.go","lineNumber":380,"sourceCode":"\t}\n\n\texecutable, err := os.Executable()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"prefork: resolve executable: %w\", err)\n\t}\n\n\targs := append([]string{executable}, os.Args[1:]...)\n\n\tcmd := &exec.Cmd{\n\t\tPath:       executable,\n\t\tArgs:       args,\n\t\tStdout:     os.Stdout,\n\t\tStderr:     os.Stderr,\n\t\tEnv:        childEnv(),\n\t\tExtraFiles: p.files,\n\t}\n\tif err = cmd.Start(); err != nil {\n\t\treturn nil, fmt.Errorf(\"prefork: start child %q: %w\", executable, err)\n\t}\n\treturn cmd, nil\n}\n\ntype childExit struct {\n\terr error\n\tpid int\n}\n\n// shutdownChildren tears down every entry in childProcs. It first cancels the\n// per-child Wait goroutines' context so any parked on a RecoverInterval backoff\n// or a sigCh send return immediately; cmd.Wait() is not tied to the context, so\n// this only strips the artificial delay from the shutdown path while still\n// letting us wait for the children to actually exit. Children are then sent\n// SIGTERM (on platforms where it is supported) and given up to grace to exit\n// before survivors are killed unconditionally. wg tracks the per-child Wait\n// goroutines and is drained before returning so no goroutine outlives prefork().\nfunc (p *Prefork) shutdownChildren(","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/prefork/prefork.go#L362-L398","documentation":"Returned by Prefork.doCommand when cmd.Start() fails to launch the child process. The library wraps the OS error along with the executable path so the developer knows which binary could not be started. Listener files were already prepared, so the failure is purely in process creation.","triggerScenarios":"The resolved executable path no longer exists or lacks execute permission; fork/clone fails due to RLIMIT_NPROC/cgroup process limits (e.g. pids.max in containers); memory exhaustion (EAGAIN from fork).","commonSituations":"Binary removed after an in-place update while preforked parent still runs; Kubernetes/container cgroup hitting the process-count limit; overcommitted host with insufficient memory to fork.","solutions":["Check the executable exists and is executable (ls -l, chmod +x) at the exact wrapped path.","Raise process limits: RLIMIT_NPROC (ulimit -u) or container cgroup pids.max.","Free memory or increase the container memory limit if the cause is EAGAIN/ENOMEM.","Redeploy/restart after binary updates so parent and child binaries match."],"exampleFix":"// before\n# k8s pod hitting pids limit\n// after\nspec:\n  containers:\n  - name: app\n    resources: { limits: { ... } }\n  # and raise cgroup pids: securityContext / pids-limit in runtime config","handlingStrategy":"try-catch","validationCode":"// Pre-flight: check the binary is executable and limits allow fork\nif fi, err := os.Stat(os.Args[0]); err != nil || fi.Mode()&0111 == 0 {\n    log.Fatalf(\"executable missing or not executable\")\n}\nvar rl syscall.Rlimit\nsyscall.Getrlimit(syscall.RLIMIT_NPROC, &rl)","typeGuard":null,"tryCatchPattern":"if err := p.Listen(addr); err != nil {\n    if strings.Contains(err.Error(), \"start child\") {\n        var ee *exec.Error\n        var xe *exec.ExitError\n        switch {\n        case errors.As(err, &ee):\n            log.Fatalf(\"cannot exec %s: %v\", ee.Name, err)\n        case errors.As(err, &xe):\n            log.Fatalf(\"child exited: %v\", err)\n        default:\n            log.Fatalf(\"spawn failed (limits/memory?): %v\", err)\n        }\n    }\n}","preventionTips":["Keep the running binary on disk; restart processes after upgrades.","Raise pids limits in containers (pids.max / --pids-limit).","Ensure adequate memory headroom for forking.","Grant execute permission in your build/packaging pipeline."],"tags":["go","prefork","process-spawn"],"backgroundTag":"fork-failed","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}