{"record":{"id":"f54478e7e2d4e9f7","repo":"run-llama/liteparse","slug":"parser-pool-is-closed","errorCode":null,"errorMessage":"parser pool is closed","messagePattern":"parser pool is closed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/node/src/pool.ts","lineNumber":252,"sourceCode":"      return;\n    }\n    const waiter = this.waiters.shift();\n    if (waiter !== undefined) waiter.resolve(worker);\n    else this.idle.push(worker);\n  }\n\n  private retire(worker: WorkerHandle): void {\n    worker.kill();\n    this.workers.delete(worker);\n    if (!this.closed) this.spawnWorker();\n  }\n\n  /** Run one parse on an idle worker.\n   *\n   * Waits for a free worker first; `parseTimeoutMs` bounds the parse itself,\n   * not the wait. */\n  async parse(payload: string | Buffer, source: string): Promise<ParseResult> {\n    if (this.closed) throw new Error(\"parser pool is closed\");\n    const worker = await this.acquire();\n    try {\n      await worker.ready();\n      const result = await worker.request(payload, this.timeoutMs);\n      this.release(worker);\n      return result;\n    } catch (e) {\n      this.retire(worker);\n      if (e instanceof WorkerTimeout) {\n        throw new ParseTimeoutError(\n          `parse of ${source} exceeded ${this.timeoutMs}ms; the worker process was killed`,\n          source,\n          this.timeoutMs!,\n        );\n      }\n      if (e instanceof WorkerCrashed) {\n        throw new Error(\n          `liteparse worker process died while parsing ${source}: ${e.message}`,","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/run-llama/liteparse/blob/22d2dd8cd7f7b9320102b57ddaf0e663ff7d15a8/packages/node/src/pool.ts#L234-L270","documentation":"Once close() has been called on a WorkerPool, all workers are shut down and parse() refuses new work by throwing 'parser pool is closed'. Using a pool after closing it is a lifecycle programming error, so the library fails fast rather than hanging on a dead worker.","triggerScenarios":"Calling `await pool.parse(...)` after `await pool.close()`; keeping a module-level pool reference that some shutdown handler already closed; a request arriving in a server after graceful shutdown closed the pool; awaiting a long queue while another code path closes the pool concurrently.","commonSituations":"Server shutdown handlers closing the pool while in-flight requests still enqueue; tests tearing down a shared pool in beforeEach; hot-reload in dev closing the old pool while stale references remain.","solutions":["Recreate a new WorkerPool instead of reusing the closed one.","Check `pool.closed` (or track lifecycle) before calling parse.","Reorder shutdown logic so the pool closes only after all pending parses finish (await outstanding promises before close()).","Inject the pool via a getter that lazily (re)creates it rather than caching a closed instance."],"exampleFix":"// before\nawait pool.close();\nconst r = await pool.parse(buf, 'doc.pdf');\n// after\nawait pool.close();\npool = new WorkerPool(cfg, poolSize, timeoutMs);\nconst r = await pool.parse(buf, 'doc.pdf');","handlingStrategy":"try-catch","validationCode":"if (pool.closed) {\n  pool = new WorkerPool(config, poolSize, timeoutMs);\n}\nawait pool.parse(buf, 'doc.pdf');","typeGuard":"const isUsable = (p) => p != null && p.closed !== true;","tryCatchPattern":"try {\n  await pool.parse(buf, 'doc.pdf');\n} catch (e) {\n  if (e.message === 'parser pool is closed') {\n    pool = new WorkerPool(config, poolSize, timeoutMs);\n    return pool.parse(buf, 'doc.pdf');\n  }\n  throw e;\n}","preventionTips":["Centralize pool lifecycle in one owner module; other code asks it for a live pool.","On server shutdown, drain in-flight requests before calling close().","In tests, recreate the pool per test instead of sharing closed instances."],"tags":["worker-pool","lifecycle","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"22d2dd8cd7f7b9320102b57ddaf0e663ff7d15a8","analyzedAt":"2026-09-08T06:09:49.009Z","contentChangedAt":"2026-09-08T06:09:49.009Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}