Skip to content

[Bug] Non-streaming provider responses can hang indefinitely after headers arrive #304

Description

@404-Page-Found

Description

The provider timeout only covers establishing the HTTP response, not consuming the response body. fetchWithTimeout() clears its timer as soon as fetch() resolves, but the non-streaming providers then call response.json() with no remaining deadline.

A provider that sends HTTP 200 headers and then stalls without completing the JSON body can therefore leave commit-echo suggest (and model discovery during init) waiting indefinitely.

Location

  • src/providers/request.ts:3-24 — timeout is cleared immediately after await fetch().
  • src/providers/openai-compatible.tscomplete() and fetchModels() await response.json() after the timeout has been cleared.
  • src/providers/anthropic.ts — same pattern in complete().
  • src/providers/cohere.ts — same pattern in complete() and fetchModels().

Current code path

const response = await fetchWithTimeout(...);
...
const data = await response.json(); // no deadline remains here

Steps to reproduce

  1. Configure a provider that reaches the configured endpoint.
  2. Have the endpoint return a successful response with headers but keep the response body open/incomplete.
  3. Run a non-streaming command such as commit-echo suggest or trigger model discovery with commit-echo init.
  4. Observe that the command does not time out.

This can be reproduced deterministically with a test server that writes the status/headers and then never finishes the JSON body.

Expected behavior

The configured provider timeout should bound both response acquisition and response-body consumption, or there should be a separate body-read deadline.

Actual behavior

The timeout ends at response headers. A stalled JSON body has no timeout and can hang the CLI until the user interrupts it.

Suggested fix

Keep the abort controller alive through body consumption, or provide a helper that reads response.text()/JSON under a deadline. Apply the same policy to model discovery and completion requests, not just SSE streaming.

Impact

A transient upstream/proxy failure can make normal suggest or init invocations hang indefinitely. This is separate from the existing streaming timeout work because the current streaming path has its own body-read handling.

Reviewed against current main at c67ff967a018d5fd4b032f6ef6a4981ac9d76a12.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingp1High priority; blocks core functionality

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions