{"record":{"id":"d571ac7c60e73e67","repo":"valyala/fasthttp","slug":"prefork-commandproducer-must-return-a-started-com","errorCode":null,"errorMessage":"prefork: commandproducer must return a started command","messagePattern":"prefork: commandproducer must return a started command","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"prefork/prefork.go","lineNumber":59,"sourceCode":"\n\t// tcpListenerFile is a hook for (*net.TCPListener).File so tests can\n\t// inject failure paths without binding a real socket.\n\ttcpListenerFile = (*net.TCPListener).File\n\n\t// ErrOverRecovery is returned when child prefork process restarts exceed\n\t// the value of RecoverThreshold.\n\tErrOverRecovery = errors.New(\"prefork: exceeding the value of recoverthreshold\")\n\n\t// ErrOnlyReuseportOnWindows is returned when running on Windows without Reuseport.\n\tErrOnlyReuseportOnWindows = errors.New(\"prefork: windows only supports reuseport = true\")\n\n\t// ErrCommandProducerNilCmd is returned when a CommandProducer returns\n\t// (nil, nil) instead of a started command.\n\tErrCommandProducerNilCmd = errors.New(\"prefork: commandproducer returned nil command\")\n\n\t// ErrCommandProducerNotStarted is returned when a CommandProducer returns\n\t// an *exec.Cmd whose Process is nil (i.e. cmd.Start() was not called).\n\tErrCommandProducerNotStarted = errors.New(\"prefork: commandproducer must return a started command\")\n)\n\n// Logger is used for logging formatted messages. Its method set is intentionally\n// identical to fasthttp.Logger so that *fasthttp.Server.Logger can be assigned\n// directly.\ntype Logger interface {\n\t// Printf must have the same semantics as log.Printf.\n\tPrintf(format string, args ...any)\n}\n\n// Compile-time check that fasthttp.Logger satisfies the local Logger interface;\n// keeps the two types in sync if either side ever evolves.\nvar _ Logger = fasthttp.Logger(nil)\n\n// Prefork implements fasthttp server prefork.\n//\n// Preforks master process (with all cores) between several child processes\n// increases performance significantly, because Go doesn't have to share","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/prefork/prefork.go#L41-L77","documentation":"ErrCommandProducerNotStarted is returned when a CommandProducer returns an *exec.Cmd whose Process is nil, which means cmd.Start() was never called. Prefork expects the producer to hand back an already-started command; merely constructing one with exec.Command is insufficient.","triggerScenarios":"A CommandProducer returns `exec.Command(\"app\", args...)` directly without calling `.Start()` on it, then prefork's doCommand validates `cmd.Process == nil` and fails.","commonSituations":"Implementations that confuse exec.Command (which only builds the Cmd) with exec.Start; refactors that removed the Start() call while keeping the return.","solutions":["Call cmd.Start() inside the CommandProducer before returning it (or return the error from Start()).","If you cannot start it yourself, use exec.Cmd only via producers that guarantee Start() was invoked.","Check cmd.Process != nil in tests for your producer."],"exampleFix":"// before\nproducer := func() (*exec.Cmd, error) {\n    return exec.Command(\"app\")\n}\n// after\nproducer := func() (*exec.Cmd, error) {\n    cmd := exec.Command(\"app\")\n    if err := cmd.Start(); err != nil { return nil, err }\n    return cmd, nil\n}","handlingStrategy":"validation","validationCode":"cmd, err := producer()\nif err == nil && (cmd == nil || cmd.Process == nil) {\n    return errors.New(\"commandproducer must return a started command\")\n}","typeGuard":"func isStarted(cmd *exec.Cmd) bool {\n    return cmd != nil && cmd.Process != nil\n}","tryCatchPattern":null,"preventionTips":["Always call cmd.Start() before returning a Cmd from a producer.","Assert cmd.Process != nil in producer unit tests.","Comment your producer contract: \"must return a STARTED command\"."],"tags":["prefork","commandproducer","exec"],"backgroundTag":"unstarted-exec-command","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}