Skip to content

openspecui.hooks.ts: McpStdioClient hangs on reqstool mcp spawn/exit failure #33

Description

@jimisola

Problem

`McpStdioClient` in `plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts` has no `proc.on('error'/'exit')` handling. If `reqstool mcp` fails to spawn (binary not on `PATH`) or the child process exits unexpectedly, all pending JSON-RPC promises — including the constructor's `this.ready` — hang forever instead of rejecting. Since `enrich()` awaits `this.ready` before every call, and `onReadDocument`'s catch block expects `enrich()` to eventually reject so it can surface a `diagnostics: [{level: "warning", ...}]` result, a broken environment causes the first document read to hang indefinitely rather than failing fast with a clear error.

Separately, `enrich()`'s result-shape cast is unvalidated:

const result = (await this.send("tools/call", {
  name: "enrich_document",
  arguments: { content, preset },
})) as { content: { text: string }[] };
return result.content[0].text;

An empty `content` array or differently-shaped result throws an opaque `TypeError` instead of a clear diagnostic.

Origin

Found during code review of reqstool-python-poetry-plugin#131 (org-wide OpenSpec/reqstool dogfooding rollout), which copies this file verbatim per the template. Filing here rather than patching downstream, since a local fix would drift from this template and need re-applying on every future sync.

Fix

  • Add `this.proc.on('error', ...)` and `this.proc.on('exit', ...)` handlers in the constructor that reject all pending promises (and the `ready` promise) with a descriptive error.
  • Guard `enrich()`'s response shape (e.g. `if (!result?.content?.[0]?.text) throw new Error(...)`) before indexing, for a clearer diagnostic message.
  • Bump the `@reqstool-openspec-hooks` template version header, the `reqstool-openspec` plugin version, and the marketplace version per CONTRIBUTING.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions