Skip to content

fix(session): encode persisted output formats - #37541

Open
edwardgushchin wants to merge 1 commit into
anomalyco:devfrom
edwardgushchin:output-format-encoding
Open

fix(session): encode persisted output formats#37541
edwardgushchin wants to merge 1 commit into
anomalyco:devfrom
edwardgushchin:output-format-encoding

Conversation

@edwardgushchin

@edwardgushchinedwardgushchin commented Jul 17, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#26929

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Persisted V1 messages hydrate output formats as plain objects. The response encoder previously used Schema.Class, which requires class instances and returned HTTP 400 when history contained either a text or json_schema format.

This changes those two wire schemas to Schema.Struct, preserving the JSON shape while allowing persisted plain objects to encode. It also adds an endpoint regression test that saves both formats, reloads them through the database, and reads them through GET /session/:id/message.

This supersedes the encoding portion of #29632. Credit to @trevorWieland for the original diagnosis and fix.

How did you verify your code works?

  • bun test --timeout 60000 test/server/session-messages.test.ts in packages/opencode — 6 passed
  • bun typecheck in packages/opencode
  • bun typecheck in packages/schema
  • Focused oxlint and Prettier checks
  • Built the Windows x64 executable and verified a live save/read round trip for both output formats

The repo-wide pre-push typecheck cannot complete in this Windows checkout because the existing packages/enterprise/src/custom-elements.d.ts symlink is checked out as literal text; both changed packages typecheck successfully.

Screenshots / recordings

Not applicable; this is an HTTP response-encoding fix with no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actionsgithub-actionsBot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Jul 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@jogoossens

Copy link
Copy Markdown

ok ,is it coming? hitting this bug too :)

@Futuri-Risk

Copy link
Copy Markdown

Commenting to give this some eyes — and because I believe it closes a severity angle that isn't obvious from the linked issue (#26929).

I'm hitting #26929 via the in-process plugin path (the opencode-claude-memoryrecall-selector agent, which sends format: { type: "json_schema", schema: {...}, retryCount: 2 } on every session.prompt). In that path the rejection isn't a one-off HTTP 400 — the SDK call retries in a tight loop (every ~5 s, >1,600/hour, indefinitely), burning LLM quota and stalling the session. Full repro + the runaway-retry + downstream-cascade detail: issue #26929 comment.

From reading this diff, the root cause it targets — the persisted OutputFormat* losing its schema identifier on read-back, so the deserialiser rejects its own persisted shape — is exactly what drives both the HTTP 400 and the retry loop (the loop is just the caller re-prompting after each failed read-back). So the added returns persisted output formats test covering json_schema is the right coverage.

Two questions / possible nits for the maintainer:

  1. Does this also cover the in-process call site (not just the HTTP /session/:id/message endpoint)? The retry loop I'm seeing is via the SDK against the running server, not a raw HTTP GET — want to make sure the encoding fix lands on the shared serialisation path both use.
  2. The retryCount field — worth confirming it round-trips too (the recall-selector format sets retryCount: 2), since the test asserts the full format object back.

If both check out, this looks mergeable as-is and would unblock every opencode-claude-memory user. Happy to test a build against the recall-selector repro if that'd help move it forward.

@rscambler

Copy link
Copy Markdown

Is there anything holding up this review? It would be great to get this fixed

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GET /session/:id/message returns 400 when messages contain format with inline JSON schema

4 participants

@edwardgushchin@jogoossens@Futuri-Risk@rscambler