{"record":{"id":"4c3539b95cbb58ba","repo":"ory/hydra","slug":"jsonnetsecure-acquire","errorCode":null,"errorMessage":"jsonnetsecure: acquire","messagePattern":"jsonnetsecure: acquire","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jsonnetsecure/jsonnet_pool.go","lineNumber":266,"sourceCode":"\nfunc (vm *processPoolVM) EvaluateAnonymousSnippet(filename string, snippet string) (_ string, err error) {\n\ttracer := trace.SpanFromContext(vm.ctx).TracerProvider().Tracer(\"\")\n\tctx, span := tracer.Start(vm.ctx, \"jsonnetsecure.processPoolVM.EvaluateAnonymousSnippet\", trace.WithAttributes(attribute.String(\"filename\", filename)))\n\tdefer otelx.End(span, &err)\n\n\tparams := vm.params\n\tparams.Filename = filename\n\tparams.Snippet = snippet\n\tpp, err := json.Marshal(params)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"jsonnetsecure: marshal\")\n\t}\n\n\tctx = context.WithValue(ctx, contextValuePath, vm.path)\n\tctx = context.WithValue(ctx, contextValueArgs, vm.args)\n\tworker, err := vm.pool.puddle.Acquire(ctx)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"jsonnetsecure: acquire\")\n\t}\n\n\tctx, cancel := context.WithTimeoutCause(ctx, 1*time.Second, errors.Errorf(\"failed to run jsonnet within 1s: filename=%s\", filename))\n\tdefer cancel()\n\tresult, err := worker.Value().eval(ctx, pp)\n\tif err != nil {\n\t\tworker.Destroy()\n\t\treturn \"\", errors.Wrap(err, \"jsonnetsecure: eval\")\n\t} else {\n\t\tworker.Release()\n\t}\n\n\tif strings.HasPrefix(result, \"ERROR: \") {\n\t\treturn \"\", errors.New(\"jsonnetsecure: \" + result)\n\t}\n\n\treturn result, nil\n}","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jsonnetsecure/jsonnet_pool.go#L248-L284","documentation":"`EvaluateAnonymousSnippet` fetches a worker from the puddle resource pool via `vm.pool.puddle.Acquire(ctx)`; any acquisition failure is wrapped as this error. Commonly this is the caller's context being cancelled/expired while waiting for a free worker, the pool being closed (ErrProcessPoolClosed), or worker construction (newWorker) failing while the pool tries to create resources.","triggerScenarios":"Calling EvaluateAnonymousSnippet when all workers are busy and the ctx expires before a worker is released; Pool.Close() was called (ErrProcessPoolClosed); underlying newWorker failures (exec, pipes, warm-up) surface through acquisition.","commonSituations":"Bursts of concurrent jsonnet evaluations exceeding pool size (min 5) with short-lived contexts; shutdown racing in-flight evaluations; the worker binary missing so pool refill keeps failing; context deadlines from upstream request timeouts.","solutions":["Check `errors.Is(err, jsonnetsecure.ErrProcessPoolClosed)` — if so, stop using the pool after Close or create a new one","Increase the pool size (NewProcessPool) to match concurrent evaluation demand","Verify the worker binary path and that newWorker succeeds (look for accompanying newWorker/warm-up errors in logs)","Check the wrapped context error: deadline/cancellation from upstream means either bigger pool or longer timeout"],"exampleFix":"// before: shared pool closed during shutdown while requests still evaluate\npool := jsonnetsecure.NewProcessPool(10)\ndefer pool.Close()\n...requests may still call vm.EvaluateAnonymousSnippet after Close → \"jsonnetsecure: acquire\"\n// after: drain work before closing\nwg.Wait() // let in-flight evaluations finish\npool.Close()","handlingStrategy":"retry","validationCode":"// before calling: ensure the pool is open and has capacity headroom\nif pool.Stat() == nil {\n    return errors.New(\"pool not initialized\")\n}\n// stat := pool.Stat(); if stat.ConstructionWorkersCount==0 && stat.TotalResources()==0 && poolRecentlyClosed { ... }","typeGuard":"func isPoolClosed(err error) bool {\n    return errors.Is(err, jsonnetsecure.ErrProcessPoolClosed)\n}","tryCatchPattern":"result, err := vm.EvaluateAnonymousSnippet(\"f.jsonnet\", snippet)\nif err != nil && strings.Contains(err.Error(), \"jsonnetsecure: acquire\") {\n    if errors.Is(err, jsonnetsecure.ErrProcessPoolClosed) {\n        return \"\", err // do not retry a closed pool\n    }\n    select {\n    case <-time.After(100 * time.Millisecond): // transient contention; retry once\n        result, err = vm.EvaluateAnonymousSnippet(\"f.jsonnet\", snippet)\n    }\n}","preventionTips":["Size the pool for peak concurrent evaluations (remember the internal minimum of 5)","Never call Pool.Close() while requests may still evaluate; drain first","Check upstream context deadlines — acquisition honors the caller's ctx","Monitor puddle stats (waiters, acquisitions) to detect saturation early"],"tags":["go","pool","concurrency","context-canceled","jsonnet"],"backgroundTag":"pool-acquire-failed","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"}