{"record":{"id":"d8a33ba17090cacc","repo":"ory/hydra","slug":"newworker-failed-to-create-stderr-pipe","errorCode":null,"errorMessage":"newWorker: failed to create stderr pipe","messagePattern":"newWorker: failed to create stderr pipe","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jsonnetsecure/jsonnet_pool.go","lineNumber":155,"sourceCode":"\t}\n\n\tin := make(chan []byte, 1)\n\tgo func(c <-chan []byte) {\n\t\tfor input := range c {\n\t\t\tif _, err := stdin.Write(append(input, 0)); err != nil {\n\t\t\t\tstdin.Close()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}(in)\n\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn worker{}, errors.Wrap(err, \"newWorker: failed to create stdout pipe\")\n\t}\n\tstderr, err := cmd.StderrPipe()\n\tif err != nil {\n\t\treturn worker{}, errors.Wrap(err, \"newWorker: failed to create stderr pipe\")\n\t}\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn worker{}, errors.Wrap(err, \"newWorker: failed to start process\")\n\t}\n\n\tspan.SetAttributes(semconv.ProcessPID(cmd.Process.Pid))\n\n\tscan := func(c chan<- string, r io.Reader, maxTokenSize int) {\n\t\tdefer close(c)\n\t\tscanner := bufio.NewScanner(r)\n\t\tscanner.Buffer(make([]byte, 0, 64*KiB), maxTokenSize)\n\n\t\tscanner.Split(splitNull)\n\t\tfor scanner.Scan() {\n\t\t\tc <- scanner.Text()\n\t\t}\n\t\tif err := scanner.Err(); err != nil {","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jsonnetsecure/jsonnet_pool.go#L137-L173","documentation":"`newWorker` calls `cmd.StderrPipe()` to capture the child's error stream; failure here aborts worker creation with this wrapped error. As with the other pipe creations, the root cause is practically always inability to allocate new file descriptors in the parent process.","triggerScenarios":"Puddle pool constructor invoking `newWorker`: `cmd.StderrPipe()` returns an error — fd exhaustion (EMFILE/ENFILE) or, rarely, the OS refusing pipe allocation (pipe-full / ENOMEM on exotic systems).","commonSituations":"Container with a tiny default nofile limit; long-lived service accumulating leaked fds until every new pipe fails; many pools or per-request VMs each spawning workers.","solutions":["Raise the process fd limit (`ulimit -n`, systemd LimitNOFILE, K8s securityContext)","Count fds via `/proc/<pid>/fd` and fix leaks — make sure `Pool.Close()` is called and workers are destroyed","Reduce concurrent pool sizes / reuse a single pool instead of creating per-request pools","If the system is genuinely out of resources, restart the service and add fd monitoring/alerting"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var lim syscall.Rlimit\nsyscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)\nif fdCount()+2 >= int(lim.Cur) {\n    return errors.New(\"cannot allocate stderr pipe: fd limit reached\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Provision adequate nofile limits before deploying jsonnet-heavy services","Leak-check long-running processes periodically","Avoid creating per-request pools; share a single Pool across the app","Include fd usage in health-check endpoints"],"tags":["go","subprocess","file-descriptors","ulimit","pipe"],"backgroundTag":"too-many-open-files","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}