valyala/fasthttp · error
prefork: commandproducer returned nil command
Error message
prefork: commandproducer returned nil command
What it means
ErrCommandProducerNilCmd is returned when a user-supplied CommandProducer callback returns (nil, nil) instead of a started *exec.Cmd. The prefork child-process machinery needs a real command to run; a nil command with nil error is treated as a programming bug, not an operating condition.
Source
Thrown at prefork/prefork.go:55
)
var (
defaultLogger = Logger(log.New(os.Stderr, "", log.LstdFlags))
// tcpListenerFile is a hook for (*net.TCPListener).File so tests can
// inject failure paths without binding a real socket.
tcpListenerFile = (*net.TCPListener).File
// ErrOverRecovery is returned when child prefork process restarts exceed
// the value of RecoverThreshold.
ErrOverRecovery = errors.New("prefork: exceeding the value of recoverthreshold")
// ErrOnlyReuseportOnWindows is returned when running on Windows without Reuseport.
ErrOnlyReuseportOnWindows = errors.New("prefork: windows only supports reuseport = true")
// ErrCommandProducerNilCmd is returned when a CommandProducer returns
// (nil, nil) instead of a started command.
ErrCommandProducerNilCmd = errors.New("prefork: commandproducer returned nil command")
// ErrCommandProducerNotStarted is returned when a CommandProducer returns
// an *exec.Cmd whose Process is nil (i.e. cmd.Start() was not called).
ErrCommandProducerNotStarted = errors.New("prefork: commandproducer must return a started command")
)
// Logger is used for logging formatted messages. Its method set is intentionally
// identical to fasthttp.Logger so that *fasthttp.Server.Logger can be assigned
// directly.
type Logger interface {
// Printf must have the same semantics as log.Printf.
Printf(format string, args ...any)
}
// Compile-time check that fasthttp.Logger satisfies the local Logger interface;
// keeps the two types in sync if either side ever evolves.
var _ Logger = fasthttp.Logger(nil)
View on GitHub (pinned to c96f600972)
Solutions
- Make the CommandProducer always return either a started *exec.Cmd or a non-nil error.
- Fix fall-through branches so they never `return nil, nil`.
- If no child should be spawned, don't install a CommandProducer / don't enable prefork.
Example fix
// before
producer := func() (*exec.Cmd, error) {
if useCmd { return exec.Command("app"), nil }
return nil, nil
}
// after
producer := func() (*exec.Cmd, error) {
if useCmd { return exec.Command("app"), nil }
return nil, errors.New("no command to produce")
} Defensive patterns
Strategy: validation
Validate before calling
cmd, err := producer()
if err == nil && cmd == nil {
return errors.New("commandproducer returned nil command")
} Type guard
func validProducedCmd(cmd *exec.Cmd, err error) bool {
return err == nil && cmd != nil
} Prevention
- Never return nil, nil from a CommandProducer — return an error instead.
- Lint/review: any `return nil` in a producer should be `return nil, err`.
- Write a table test covering every branch of your CommandProducer.
When it happens
Trigger: Passing a CommandProducer to prefork that returns nil for the command and nil for the error, e.g. `func() *exec.Cmd { return nil }`, then starting the preforker (doCommand path).
Common situations: Custom command producers copied from examples and stubbed out with `return nil`; conditional logic in the producer that silently falls through without returning a command or an error.
Related errors
- prefork: commandproducer must return a started command
- prefork: exceeding the value of recoverthreshold
- prefork: windows only supports reuseport = true
- prefork: close inherited listener fd: %w
- prefork: resolve %s/%s: %w
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/7a964e517834cc97.
Report an issue: GitHub.