API 400 or Upstream Error: Should You Fix the Request or Retry?
An API 400 or upstream error is not automatically a model outage. Inspect the error body, check Responses and Messages parameters, and distinguish safe retries from interrupted streams with completed tool actions.
The request fails. Your application displays “upstream error,” and the next attempt displays exactly the same thing. Somewhere behind that message is a reason to change a parameter, check access, or wait. The interface has not told you which.
An API 400 usually points you toward the request; “upstream error” only identifies a failure farther along the call chain. Neither phrase, on its own, proves a model outage. For developers connecting an application to an LLM API, the useful first move is to inspect the actual error body before replacing the model or adding another retry loop. SandBase’s documented compatible endpoints provide concrete examples of why the distinction matters.
Key takeaway
- For API 400, inspect the request format and supported model features before resending the same body.
- Keep the HTTP status, error body and endpoint together. “Upstream error” is not a diagnosis.
- A 429 or some 5xx failures may justify limited retries, but only when repeating the operation is safe.
- Receiving streamed text is not proof of completion. The application must recognize the protocol’s normal ending.
Find the response behind the message
“Something went wrong, try again” is application copy. It may not be the server’s explanation. If your backend sends the model request, inspect the response received by that backend. If the browser makes the request directly, its Network panel is the relevant place to start. Looking only at the final notification can leave the most useful details out of the investigation.
The SandBase error guide explains that its endpoint families do not share one universal error JSON shape. OpenAI-compatible operations normally have an error object, Anthropic Messages uses its compatible envelope, and some platform operations can return a flat error string.
That means a parser written for one protocol can fail while handling another. If application code assumes error.param always exists, the error handler may throw a second exception and obscure the first failure. Optional diagnostic fields need a fallback, not another failure path.
Read whatever specific explanation the response provides. A message identifying an unsupported field gives you a reason to check that field against the selected model. It does not give you a reason to rotate a credential. Conversely, if the body remains generic, resist filling in the missing cause yourself. Retain the status, request time and any returned request identifier so a support investigation can find the same event.
The model can be the same while the request format changes
Switching endpoints is not just replacing a URL.
SandBase’s Responses API reference uses input for the request and returns generated items in output. Chat Completions uses messages and choices. A body copied from Chat Completions should not be assumed valid for /v1/responses, even if the model is available through both protocols.
An endpoint change can require changes to both the request body and the code reading the result.
The Anthropic Messages API reference describes another set of conventions. System instructions belong in the top-level system field, conversation messages use user and assistant roles, and max_tokens is a required output limit. Images, tools and extended thinking also depend on what the selected model supports. A compatible connection is not a promise that every optional feature works with every model.
For a large failing request, reduce the number of things under investigation. Keep the endpoint and public model identifier fixed, and simplify the request to ordinary text. If that works, restore one category of content at a time: the image, then the tool definitions, then additional parameters. A failure returning after one addition tells you much more than a successful request after changing five things simultaneously.
This method still makes real calls and can incur inference charges. Limit the attempts, and preserve a sanitized record of the original failure before simplifying anything. Otherwise you may end up with a working small example and no record of what made the original different.
There is also a distinction between constructing a request and reading its result. A successful response followed by an application exception is not necessarily an API failure. When changing protocols, verify the output field as carefully as the input field. An application still looking for choices cannot be expected to interpret a Responses result correctly.
When another attempt helps—and when it does not
A 400, a 429 and a 503 can all look like the same failure to an end user. They should not enter the same application retry loop. SandBase’s published guidance suggests different next steps:
| Status | Investigate first |
|---|---|
| 400 / 422 | Request format, parameters or unsupported model capabilities |
| 401 | A missing, invalid or revoked credential |
| 403 | Permission to access the resource |
| 402 | Balance or spending controls |
| 429 | A returned Retry-After value and an appropriate wait |
| 500 / 502 / 503 / 504 | Whether repeating the operation is safe before limited retries |
Nearby status codes can call for very different actions. Not every endpoint emits every status in the table.
The Responses reference is more specific: 502 can mean the upstream response could not be safely parsed and sanitized; 503 covers failed routing or exhausted provider candidates. A 502 is therefore not enough to conclude that a server is simply busy. If the same request continues failing, retain its diagnostics rather than indefinitely increasing the retry count.
Waiting does not add a missing permission. A replacement key does not make an unsupported parameter valid. That is why the specific response matters even after an application has classified the status.
For temporary failures that are safe to repeat, backoff increases the waiting time between attempts. Jitter adds a small random delay so many clients do not return together. Respect Retry-After when the response supplies it, and put a limit on both the number of attempts and the total time spent.
Before adding that loop, check the SDK—the client development library—already in use. It may perform its own retries. An application wrapper around those retries can multiply actual calls. Let one layer own the policy, or include both layers when calculating the attempt and timeout budget. Counting iterations in your outer loop is not the same as counting requests sent to the service.
Regenerating a failed summary can be acceptable when any valid answer will do. It can still create another charge and a different answer. The case becomes more serious when the model interaction includes a tool that creates an order, publishes a page or changes a record. Repeating a text generation and repeating a business action are different decisions.
A partial answer is not a completed stream
HTTP 200 is insufficient to establish that an entire streamed answer finished. A connection can be established successfully and later carry an error event or disconnect after some text has arrived.
The Messages event documentation describes events including message_start, content-block events and message_stop. The application needs to handle protocol-level errors and recognize the normal completion signal for the protocol it selected. Counting a few chunks of output is not a substitute.
Content arriving and a message completing are separate events. The interface should preserve that distinction.
Keeping partial output can be useful, provided it is marked incomplete. Silently saving half a summary as a successful result makes a transport failure into a data-quality problem. Code generation has the same issue: visible code is not necessarily the complete file the application requested.
Now consider a tool action that already happened. Suppose an agent created an order before its final response disconnected. Retrying the narration does not need to create the order again. A timeout establishes that the client stopped waiting, not that the server did nothing. Inspect the documented task or resource state before replaying an ambiguous operation.
If an endpoint offers idempotency, use its documented mechanism to prevent repeat submissions from repeating the action. Do not invent a header and assume the server recognizes it. Without that guarantee, reconciliation has to come before another state-changing request. The streaming guide is the appropriate reference for protocol-specific behavior; reconnecting should not be described as lossless resume unless the selected API promises it.
Save enough to investigate, not everything you have
A useful error record includes the endpoint, public model identifier, request time, HTTP status, available error type, attempt count and elapsed time. Record whether any content arrived before the failure, and retain a returned request identifier when available. These details distinguish an immediate rejection from an interrupted response.
For interactions spanning several tools, agent logging and request tracing explains how to connect related events. The purpose is to follow one operation across its steps without losing where it failed.
Authorization headers, keys, customer text and unredacted upstream responses do not belong in a public issue. Specific diagnostics do not require copying the entire conversation. Remove sensitive content and provide the smallest request that still demonstrates the problem. That gives the person investigating something more useful than a screen of unrelated logs—and avoids making a support ticket a second security problem.
FAQ
Does API 400 mean the account has insufficient credit?
Do not infer that. SandBase’s documentation associates billing restrictions with 402; for 400, inspect the request first. The actual endpoint and response body still matter more than a simplified interface notification.
Does upstream error mean the model is down?
No. The label does not identify a cause. Combine the HTTP status with available details to distinguish a request issue from a limit or temporary service failure.
What if param or request_id is missing?
Those fields are not guaranteed across all endpoints. Accept absent optional values and retain the diagnostics that are present. An error parser should not throw another exception because a field was omitted.
Can an interrupted stream resume from the same point?
Do not assume it can. Repeating the request generally creates a new generation. If tools have executed, first reconcile their effects, then follow the selected API’s documented behavior.
The useful outcome is not turning every failure into an automatic retry. It is knowing what deserves to change before the next request. Preserving a specific, sanitized error response is often the first step toward that answer.




