Skip to content

About

Error from provider (Console): Upstream request failed: [invalid_request_error] reasoning `encrypted_content` was not issued to this caller

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

opencode-sanitize-reasoning

Shield against stale reasoning.encrypted_content after OpenCode restarts and idle gaps.

Note

If this plugin saved your old chats, consider supporting the author and checking out my other projects:

Problem

Reasoning models behind the Responses API return an opaque crypto blob (metadata.openai.reasoningEncryptedContent + metadata.openai.itemId) that is bound to the caller/key that issued it. OpenCode persists it in session parts. When the blob goes stale, the next request replays it and the upstream rejects the whole request:

  • reasoning 'encrypted_content' was not issued to this caller
  • invalid_encrypted_content

Two confirmed triggers (opencode/muse-spark-1.3-contributor-free via Zen):

  1. Server-process restart - the Zen pool serves the next request from a different caller/key, so every pre-restart blob is unverifiable.
  2. Short upstream TTL - blobs expire within minutes of idle time, so even blobs born in the live process go stale mid-session. Manually rewinding the chat ("reset to this point") confirms it: the rewind drops the stale tail and the next message succeeds, until fresh blobs expire again.

What it does

Before every model request (experimental.chat.messages.transform), it drops the crypto blob and itemId from reasoning parts that are EITHER older than the current server-process boot time OR older than a configurable max age (default 3 minutes). The human-readable textsummary always stays - the model re-derives reasoning from history (documented stateless fallback). Fresh blobs are never touched, so the live reasoning cache keeps working.

The default export is a { id, setup, server } object (same shape as opencode-prune-images): the 1.18.x loader resolves server directly (v1 path). A function-style default export is not usable here - the legacy scan requires every module export to be a plugin function, otherwise loading fails with Plugin export is not a function.

Configuration

Variable Default Meaning
OPENCODE_SANITIZE_REASONING on off turns every hook into a no-op (kill-switch).
OPENCODE_SANITIZE_REASONING_MAX_AGE_MINUTES 3 Max blob age in minutes (fractional allowed, e.g. 0.5 = 30s). off, 0 or negative disables the age rule (restart-only mode). Unset/empty/unparsable falls back to the default.

Safety (do-no-harm first)

  • Fail-open: any exception leaves the payload untouched.
  • Conservative match: type === "reasoning" + non-empty string blob + finite numeric time.start + (start < bootTs OR age over max-age). Anything ambiguous is left alone.
  • Minimal diff: only the two metadata keys are removed; part id, text and the rest of metadata stay intact.
  • Zero writes: no DB, no files, no network. Only the in-memory request payload is mutated.
  • Observable: loaded and stripped N ... lines go to stderr, which lands in opencode.log - check there that the plugin is active.

Usage

Point OpenCode at this plugin in ~/.config/opencode/opencode.json:

{
  "plugin": [
    "file:///Users/foobar/projects/opencode-sanitize-reasoning/index.ts"
  ]
}

Then fully restart OpenCode Desktop so the plugin loads.

Development

npm install
npm test           # node --test index.test.ts
npm run typecheck  # tsc --noEmit

Manual acceptance:

  1. Restart the Desktop -> continue a previously broken old chat from the first message; look for stripped N stale reasoning blob(s) in the log.
  2. Idle 5+ minutes in a working chat -> the next message succeeds on the first try (age rule strips the expired blob).
  3. Rapid message chain -> no stripped entries in the log (live cache intact).
  4. OPENCODE_SANITIZE_REASONING=off -> behavior identical to no plugin.

Rollback

Remove the plugin line from plugin[] in opencode.json and restart the Desktop.

About

Error from provider (Console): Upstream request failed: [invalid_request_error] reasoning `encrypted_content` was not issued to this caller

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages