Repository navigation
fix(conversations): read message history stored as jsonb - #337
Merged
Merged
Conversation
messages.content is a jsonb column, and Postgres reorders object keys,
so the MessageBlock "$type" discriminator is no longer the first
property when a message is read back. The source-generated reader then
threw NotSupportedException ("must specify a type discriminator") in
PostgresMessageStore.MessageRow.ToMessage(), and every message read on
Postgres answered 500. Latent since message storage first shipped (1.2.0).
Set AllowOutOfOrderMetadataProperties on ConversationsJsonContext. The
shared PostgresJsonContext also registers MessageEnvelope for jsonb
columns; it gets the same setting, in both its attribute and the
explicit options PostgresJson.Ctx is built with (those replace the
attribute wholesale). No other polymorphic type is serialized in
Platform.
Tests over a real Postgres 18 (Testcontainers) cover
GetConversationMessagesAsync, GetByIdAsync, FindByExternalIdAsync and
GetByConversationIdsAsync with text and image blocks, every block type,
and a row written by an earlier release. No migration is needed.
This was referenced Oct 4, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every read of a stored message on PostgreSQL failed with a 500 (
NotSupportedExceptionatPostgresMessageStore.cs:188).messages.contentisjsonb, which reorders object keys, so aMessageBlock's$typediscriminator is no longer the first property when read back, and System.Text.Json requires it first by default.The fix sets
AllowOutOfOrderMetadataProperties = trueonConversationsJsonContext(the read path) and onPostgresJsonContextplus its explicitPostgresJson.Ctxoptions (same latent bug; nothing reads messages through it today).Latent since message storage first shipped (1.2.0). Found in the LAB-W1 measurement (Platform 2.25.0 + Web 3.20.x against Postgres).
Tests (written first, red on main)
Stores/PostgresMessageStoreJsonbTests.cs: everyIMessageStoreread, all seven block types, a row inserted by hand in the format earlier releases stored (no migration needed), and a control that showsjsonbreally moves$type. 6 of 7 failed on main with the production exception; the control passes by design.PostgresJsonContextTests.cs, 1 unit test inMessageBlockTests.cs.Gate (rebased on f8164ff, which includes the Sdk 2.7.0 cascade #332)
Release build 0 warnings · unit lane 4313/4313 · Storage.Postgres 344/344 · Identity.Redis 34/34 · coverage floor OK · endpoint invariants · script tests · OpenAPI export + fixture checks · Native AOT publish 0 IL warnings ·
codeql-branch: 0 results on added lines.An adversarial review confirmed the cascade adds no JSON context, converter or store path that bypasses the fix, and that
MessageBlockis the only polymorphic type persisted.🤖 Generated with Claude Code