Skip to main content

A stop generation button is available during generation

ab-000142 · ai-chat-visibility.loading-and-streaming.stop-generation-button
Severity: highactive

Why it matters

Without a stop button the user is held hostage by every generation they regret starting: a prompt that is clearly going off the rails, a response already too long, a hallucination cascading into more hallucinations. They cannot terminate the stream, cannot re-prompt, and the product burns their tokens and wall-clock time on output they will immediately delete. This is one of the most-cited usability gaps in AI chat products and directly affects token-spend efficiency for paying users.

Severity rationale

High because users cannot recover from a bad generation and the product wastes their tokens on discarded output.

Remediation

In src/components/chat/ChatInput.tsx, swap the Send button for a Stop button while isLoading is true and wire it to the stop() function from useChat (or to controller.abort() for custom AbortController-based fetches). The partial response should remain visible after stopping.

{isLoading ? (
  <Button onClick={stop} variant="destructive">Stop</Button>
) : (
  <Button type="submit">Send</Button>
)}

Detection

  • ID: ai-chat-visibility.loading-and-streaming.stop-generation-button

  • Severity: high

  • What to look for: Check whether a stop/cancel button appears while the AI is generating a response. In the Vercel AI SDK, this is the stop() function from useChat. In custom implementations, look for AbortController usage that allows cancellation. The button should be visible and functional during streaming. Count the cancellation mechanisms present (AbortController, stop(), custom abort logic).

  • Pass criteria: A stop/cancel button is rendered and functional while generation is in progress. Clicking it halts the stream and leaves the partial response visible. The input becomes re-enabled after stopping. At least 1 abort mechanism must be wired to the button.

  • Fail criteria: No stop button exists, or a stop button exists but is always disabled or hidden. Users must wait for the full response to complete even if it is clearly wrong or too long.

  • Skip (N/A) when: The AI interface operates in strictly non-streaming mode and responses are short enough that stopping is not meaningful (average response under 2 seconds). Signal: no streaming detected in API calls and responses are short-form.

  • Detail on fail: "No stop generation button found; users cannot interrupt long or incorrect responses during generation"

  • Remediation: In your input component at src/components/chat/ChatInput.tsx, toggle between Send and Stop:

    {isLoading ? (
      <Button onClick={stop} variant="destructive">Stop</Button>
    ) : (
      <Button type="submit">Send</Button>
    )}
    

    For custom fetch implementations, create an AbortController, pass its signal to the fetch call, and invoke controller.abort() on the stop button click.

  • Cross-reference: For button state management and accessible toggle patterns, the Accessibility Fundamentals Audit covers dynamic ARIA state changes.

Taxons

History