Skip to content

OpenAI previous_response_not_found: Causes and Fixes ​

You continue a Responses API conversation with previous_response_id and get HTTP 400: "Previous response with id 'resp_…' not found." Here is what the API needs in order to resolve that ID, the five situations where it can't, and the stateless pattern that avoids the error.

Quick answer

previous_response_not_found means the API cannot load the response you referenced, so it cannot rebuild the earlier context. The usual causes: the original call ran with store: false (or under Zero Data Retention), the response is older than the 30-day retention, it was deleted, or the ID came from a different provider or account. The durable fix is to stop depending on server-side state: keep the conversation yourself, send the full input each turn with store: false, and carry reasoning forward via encrypted_content.

Symptoms and What the Error Means ​

The body, as raised by OpenAI's Python SDK:

json
{
  "error": {
    "message": "Previous response with id 'resp_abc123' not found.",
    "type": "invalid_request_error",
    "param": "previous_response_id",
    "code": "previous_response_not_found"
  }
}

OpenAI's error-code guide describes previous_response_not_found as a previous_response_id that cannot be resolved from available state. It is a hard failure: the API won't continue without that context, and retrying with the same ID gives the same result.

A closely related failure happens when you replay output items that carry server IDs while store is off:

text
Item with id 'rs_…' not found. Items are not persisted when `store` is set to false. Try again with `store` set to true, or remove this item from your input.

Same root cause — you referenced something by ID that was never saved — and the same fix below.

Why It Happens ​

  1. The original response was created with store: false. store defaults to true when omitted, but many clients and frameworks set it to false for privacy. A response that was never stored can't be referenced later. This shows up in OpenAI's agents SDK issue tracker when a session ran with store=False and a later step tried to chain from it.
  2. Zero Data Retention. OpenAI's data-controls guide says that under ZDR the store parameter is always treated as false, even if the request sets it to true — so chaining never works in a ZDR organization.
  3. Retention expired. Response objects are kept for 30 days by default. A job that resumes a thread after that window will hit this error.
  4. The response was deleted. If your code (or a cleanup job) deletes responses, their IDs become unresolvable.
  5. The ID came from somewhere else. A response ID only means something to the service that created it. An ID from api.openai.com sent to a gateway, an ID from one gateway sent to another, or a load balancer that sends turn two to a different provider than turn one — all fail. OpenAI's docs don't spell out the exact account scope of stored responses, so treat each ID as private to the key and endpoint that produced it.

Also note that previous_response_id cannot be combined with the conversation parameter — use one state mechanism per request.

Fix 1: Send the Full Input Yourself (Stateless Mode) ​

This is the approach that works everywhere: you own the history, and every request carries all of it.

python
from openai import OpenAI

client = OpenAI(api_key="sk-YOUR_TOKEN", base_url="https://byesu.com/v1")

history = [{"role": "user", "content": "Plan a migration from REST polling to webhooks."}]

resp = client.responses.create(
    model="gpt-6.1-sol",
    input=history,
    store=False,
    include=["reasoning.encrypted_content"],   # harmless where it's already the default
)
print(resp.output_text)

# Carry the model's output items (messages, reasoning, tool calls) forward
history += resp.output
history.append({"role": "user", "content": "Now list the risks."})

resp = client.responses.create(
    model="gpt-6.1-sol",
    input=history,
    store=False,
    include=["reasoning.encrypted_content"],
)
print(resp.output_text)

Why this works:

  • Nothing to look up. With no previous_response_id, there is no server-side state to go missing.
  • Reasoning still carries over. OpenAI's reasoning guide says that in stateless mode (store: false or ZDR), reasoning items include an encrypted_content property by default; passing those items back lets the model continue its reasoning. The API still accepts reasoning.encrypted_content in include for compatibility.
  • Tool loops are unchanged. For function calling, append the model's function-call items and your function_call_output items to history exactly as you would in any stateless loop.

If a provider rejects replayed items with the "Item with id … not found" message above, strip the id field from replayed items before sending — that error has been reported for some stateless proxy setups in OpenAI's Codex tracker.

Cost note: this is not inherently more expensive in tokens than chaining. OpenAI's conversation-state guide states that with previous_response_id, all previous input tokens in the chain are still billed as input tokens. Long histories grow either way — see context length exceeded for trimming and compaction, which also works with store: false.

Fix 2: Fall Back Automatically When Chaining Fails ​

If you want to keep previous_response_id where it works (for example on OpenAI with storage on), keep a local copy of the history anyway and fall back to it when the ID can't be resolved:

python
import openai

def continue_turn(prev_id, history, new_user_msg, model="gpt-6-sol"):
    history.append({"role": "user", "content": new_user_msg})
    try:
        resp = client.responses.create(
            model=model,
            previous_response_id=prev_id,
            input=[{"role": "user", "content": new_user_msg}],
        )
    except openai.BadRequestError as e:
        if getattr(e, "code", None) != "previous_response_not_found":
            raise
        # Chain is gone: replay the whole conversation statelessly
        resp = client.responses.create(
            model=model,
            input=history,
            store=False,
            include=["reasoning.encrypted_content"],
        )
    history += resp.output
    return resp

Without the local copy there is nothing to fall back to — the earlier turns were only on the server that just told you it doesn't have them.

Fix 3: Don't Chain Across Providers ​

If your traffic can move between endpoints — failover between OpenAI and a gateway, multiple gateways, or a router that picks per request — a previous_response_id from one leg will not resolve on another. Gateways may not persist responses at all, or may route a follow-up to a different upstream, so don't rely on previous_response_id across providers. Use the stateless pattern from Fix 1 for any multi-provider setup.

If you are on OpenAI directly and want durable server-side state, the Conversations API gives you a long-lived conversation ID; OpenAI notes that conversation items are not subject to the 30-day TTL. It is still provider-specific, so the same portability caveat applies.

Codex and Other Agent Clients ​

Coding agents hit this when they assume server-side state. The history of OpenAI's Codex is a useful reference:

  • The original Codex CLI added a disable_response_storage option for ZDR organizations, so the client stored response items itself.
  • In September 2025, Codex PR #3212 ("Never store requests") removed that option, and later changes set store: false on every Responses request. Current Codex keeps the history locally and replays it with encrypted reasoning, so it does not depend on previous_response_id over HTTP. Older guides and configs that still include disable_response_storage = true come from that earlier period; current releases no longer read the option.
  • Codex's source does use previous_response_id on its Responses WebSocket transport. For custom providers, the supports_websockets setting defaults to false; leave it off unless the provider explicitly supports Responses WebSocket mode.

The byesu Codex CLI guide shows a working provider config for https://byesu.com/v1.

If You're Calling GPT Through byesu ​

byesu is an AI API gateway with an OpenAI-compatible endpoint at https://byesu.com/v1, supporting both Chat Completions and Responses, billed pay-as-you-go with no subscription.

  • Prefer stateless requests. Send the full input with store: false as in Fix 1; it behaves the same on every OpenAI-compatible endpoint and removes this error class entirely.
  • Never reuse IDs across endpoints. A resp_… ID created on another provider won't resolve here, and the reverse is also true — keep your own history for anything that might switch endpoints.

To get set up, follow the Quick Start.

FAQ ​

What does previous_response_not_found mean? ​

It is a 400 invalid_request_error with param previous_response_id. The Responses API could not resolve the ID you passed from the state available to it, so it cannot continue that chain. Nothing is generated; retrying with the same ID fails the same way.

Why is my response ID not found right after I created it? ​

Most often the original request ran with store set to false, so the response was never saved. Organizations under Zero Data Retention are treated as store: false even if you send true. The other common cause is sending the ID to a different provider or endpoint than the one that created it.

How long are Responses API responses stored? ​

OpenAI stores Response objects for 30 days by default when store is true, which is the default when omitted. After that the ID can no longer be used with previous_response_id. Items added to a Conversation object are not subject to the 30-day TTL.

How do I continue a conversation without previous_response_id? ​

Keep the conversation yourself: append each response's output items to your own input list and send the full list on every request with store set to false. Reasoning items then carry encrypted_content so reasoning state continues across turns without anything stored server-side.

Does Codex still need disable_response_storage? ​

The option was removed from the Codex codebase in September 2025 (openai/codex PR #3212), and current Codex sends store: false on every Responses request. Codex keeps the history locally and resends it, so it does not depend on previous_response_id over HTTP.

Got a problem? Contact support or join our group.