FormatError returns a user-friendly error message for model errors. Overflow errors get a kind-specific actionable message; other errors fall through to err.Error(). For HTTP errors that text comes from *StatusError, which itself extracts structured provider details (see parseProviderError). The me
(err error)
| 624 | // LLM providers and the cap that triggered the rejection is a deployment |
| 625 | // detail of the provider, not something the user can act on by name. |
| 626 | func FormatError(err error) string { |
| 627 | if err == nil { |
| 628 | return "" |
| 629 | } |
| 630 | |
| 631 | switch OverflowKindOf(err) { |
| 632 | case OverflowKindWire: |
| 633 | return "Your message is too large for the AI provider. " + |
| 634 | "Try a smaller paste, attach the file separately, or split the content." |
| 635 | case OverflowKindMedia: |
| 636 | return "An image or file in this conversation is too large for the AI provider. " + |
| 637 | "Try a smaller file or remove it from context." |
| 638 | case OverflowKindTokens: |
| 639 | return "The conversation has exceeded the model's context window and automatic compaction is not enabled. " + |
| 640 | "Try running /compact to reduce the conversation size, or start a new session." |
| 641 | } |
| 642 | |
| 643 | if IsStreamTruncationError(err) { |
| 644 | return "The connection to the model was closed unexpectedly before it completed its response. " + |
| 645 | "With local models (e.g. Docker Model Runner), this can happen when an idle or " + |
| 646 | "connection timeout in the model server (or a proxy in front of it) drops a silent " + |
| 647 | "prefill before the first token, or cuts a long response mid-stream. " + |
| 648 | "Try a shorter prompt, or raise the model server's idle/keep-alive timeout." |
| 649 | } |
| 650 | |
| 651 | return err.Error() |
| 652 | } |
| 653 | |
| 654 | // requestIDRegex matches the `(Request-ID: <id>)` segment that anthropic-sdk-go |
| 655 | // and openai-go append between the status text and the response body. |