Skip to content

[Bug] prepare-commit-msg hook blocks every commit on LLM latency with no overall timeout #271

Closed

Description

@404-Page-Found

Summary

The prepare-commit-msg hook runs buildProfile() + generateSuggestions() synchronously inside the git commit path. The hook has no overall deadline of its own — a slow or stalled provider delays every commit for up to the per-request timeout (30s, src/providers/request.ts:1), and a provider outage adds seconds of latency to each commit before degrading to a warning. To an end user, git commit appears to hang.

Location

  • src/git/hook.ts:196-208 — runPrepareCommitMsgHook: LLM calls block commit
  • src/providers/request.ts:1 — DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS = 30_000

Code snippet

// src/git/hook.ts (inside prepare-commit-msg, blocks `git commit`)
const profile = await deps.buildProfile(config.historySize);
const { suggestions } = await deps.generateSuggestions(config, diffResult.diff, profile);
const selected = suggestions[0];
...
await deps.writeMessageFile(args.messageFile, nextContent);

Suggested fix

Give the hook a tight overall deadline (e.g. abort suggestion generation after a few seconds and leave the commit message unchanged), so provider slowness can never block a commit for the full 30s. Consider also skipping the LLM call entirely when the provider appears unreachable (fast health check) or when --no-verify semantics apply.

Impact

  • Every commit's latency is coupled to LLM provider health; a hung provider stalls all commits for up to 30s each.
  • Users who install the hook and later hit a provider outage perceive git itself as broken.

Activity

  1. added this to the v0.3.0 milestone on Aug 7, 2026
  2. modified the milestones: v0.3.0, v0.4.0 on Sep 20, 2026
  3. 404-Page-Found commented on Sep 22, 2026

    @404-Page-Found
    ContributorAuthor

    Triage update:

    Confirmed on current main:

    • runPrepareCommitMsgHook() awaits buildProfile() and generateSuggestions() directly on the git commit path.
    • Provider non-streaming requests use the 30s DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS, so a slow/unreachable provider can make git commit appear hung.
    • The hook catches provider errors and continues, so the impact is primarily commit latency rather than a rejected commit.
    • There is a second timeout gap: fetchWithTimeout() clears its timer once response headers arrive, while non-streaming providers then await response.json(). A stalled response body can therefore exceed the nominal 30s timeout.

    Recommended fix:

    1. Add a small hook-specific overall deadline (e.g. 3–5s) with abort propagation through the provider request.
    2. On timeout/failure, leave the commit message unchanged, clear pending hook state, warn, and allow the commit to proceed.
    3. Keep the normal provider timeout for non-hook commands.
    4. Add regression tests for a never-resolving hook request and for a response that stalls after headers.

    A simple Promise.race() timeout without cancellation is not sufficient because the underlying provider request could continue after the hook returns.

  4. 404-Page-Found commented on Sep 22, 2026

    @404-Page-Found
    ContributorAuthor

    Implemented the fix in PR #322: #322. The prepare-commit-msg path now has a 5s overall deadline with abort propagation, keeps provider timeouts active through non-streaming response-body reads, and leaves the commit message unchanged on timeout. Regression coverage was added for both a stalled hook request and a stalled response body.

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

Metadata

Metadata

Labels

bugSomething isn't workinggood first issueGood for newcomersp1High priority; blocks core functionality

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions