ory/hydra · error

newWorker: missing binary path in context

Error message

newWorker: missing binary path in context

What it means

newWorker (oryx/jsonnetsecure/jsonnet_pool.go:125) spawns the jsonnet worker subprocess using the binary path stored in the context under contextValuePath. If that context value is absent or empty, no executable can be launched and construction of a pool worker fails with this error.

Source

Thrown at oryx/jsonnetsecure/jsonnet_pool.go:125

func (*pool) private() {}

func (p *pool) Close() {
	p.puddle.Close()
}

func (p *pool) Stat() *puddle.Stat {
	return p.puddle.Stat()
}

func newWorker(ctx context.Context) (_ worker, err error) {
	tracer := trace.SpanFromContext(ctx).TracerProvider().Tracer("")
	ctx, span := tracer.Start(ctx, "jsonnetsecure.newWorker")
	defer otelx.End(span, &err)

	path, _ := ctx.Value(contextValuePath).(string)
	if path == "" {
		return worker{}, errors.New("newWorker: missing binary path in context")
	}
	args, _ := ctx.Value(contextValueArgs).([]string)
	cmd := exec.Command(path, append(args, "-0")...)
	cmd.Env = []string{"GOMAXPROCS=1"}
	cmd.WaitDelay = 100 * time.Millisecond

	span.SetAttributes(semconv.ProcessCommand(cmd.Path), semconv.ProcessCommandArgs(cmd.Args...))

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return worker{}, errors.Wrap(err, "newWorker: failed to create stdin pipe")
	}

	in := make(chan []byte, 1)
	go func(c <-chan []byte) {
		for input := range c {
			if _, err := stdin.Write(append(input, 0)); err != nil {
				stdin.Close()

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Evaluate snippets through the public API (MakeSecureVM + EvaluateAnonymousSnippet) which injects the binary path into the context.
  2. If constructing a VM manually, ensure NewProcessPoolVM receives opts with jsonnetBinaryPath set (WithJsonnetBinary(path) or the default os.Executable()).
  3. Do not call puddle Acquire/CreateResource with an un-enriched context; only use contexts produced by EvaluateAnonymousSnippet.
  4. Verify vm.path is non-empty before evaluation; os.Executable() failing silently in newVMOptions can yield an empty path.

Example fix

// before: pool constructor called directly with bare context
w, err := puddle.CreateResource(context.Background()) // missing binary path

// after: go through the VM API which injects the path
vm, _ := jsonnetsecure.MakeSecureVM(pool)
out, err := vm.EvaluateAnonymousSnippet("config.jsonnet", snippet)
Defensive patterns

Strategy: validation

Validate before calling

if vmPath == "" {
    return errors.New("jsonnetsecure: jsonnet binary path is empty; set WithJsonnetBinary or ensure os.Executable() works")
}

Prevention

When it happens

Trigger: Acquiring a worker with a context that was not enriched with contextValuePath/contextValueArgs — i.e. any worker creation that did not go through processPoolVM.EvaluateAnonymousSnippet, which sets vm.path via WithJsonnetBinary (or the os.Executable default) into the context.

Common situations: Calling pool internals or puddle's CreateResource directly with a plain context.Background(); embedding the package and bypassing EvaluateAnonymousSnippet; a regression that drops the context values before Acquire, e.g. after WithContext replaced the context chain incorrectly (context values set on a different context than the one used for acquisition).

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/21c006bead2cf81a. Report an issue: GitHub.