Skip to content

Withhold a render failure the environment caused, at the row that publishes it - #6075

Open
backspace wants to merge 2 commits into
mainfrom
cs-12762-skip-error-stamping-for-a-stale-shell-failure
Open

Withhold a render failure the environment caused, at the row that publishes it#6075
backspace wants to merge 2 commits into
mainfrom
cs-12762-skip-error-stamping-for-a-stale-shell-failure

Conversation

@backspace

Copy link
Copy Markdown
Contributor

The indexer stores a failed render as the card's content, so a render that resolves current realm source against a bundle predating an export turns a few minutes of deploy overlap into an error document served from cache to every anonymous reader until something reindexes the row.

The decision has to be made where the row is written. A prerender server can delay a write but never prevent one — answering retryably only spends the client's retry budget and then the same row lands with a different message, and the manager prunes a server that answers 5xx, walking its registry as it goes. So the server states what it knows and the write site acts on it.

The server is the only place holding both tokens at the moment of the render, so it reaches the conclusion: a missing export that survived a re-render on a pool that still cannot be shown to have been on the shell being served describes the environment, not the card. It marks the response and returns the failure unchanged.

The write site tests for the mark's presence and nothing else. It does not re-derive the conclusion, so the rule has one implementation rather than two that drift, and absence means "no verdict" rather than "attributable" — nothing is withheld by default. When the mark is present and a prior published row exists, the row keeps the content the last good pass left: pristine_doc and its neighbours were already carried forward there, and this only declines to stamp has_error and error_doc over them. The published search_doc stays too, since the error's sparse one describes a render whose result is not being published.

Two gates keep the suppression from hiding a real break. It requires a prior published row, because a brand-new card has no good content to protect and withholding its error would leave nothing at all. And it requires the missing export to be the failure rather than merely appear among the console errors merged onto it — the broader test is right for driving one more render, where being wrong costs a render, and wrong for withholding a row, where being wrong hides a genuine break.

Tests state both directions, since the difference is the whole point: a pool that never reaches the current shell is marked, a genuine break on a recycled pool is not, and a timeout that merely mentions a missing export is not. Substituting the broad predicate for the narrow one fails that last case and only that case — the first draft of these tests did not distinguish them, which is why it is there.

…lishes it

The indexer stores a failed render as the card's content, so a render that
resolves current realm source against a bundle predating an export turns a few
minutes of deploy overlap into an error document served from cache to every
anonymous reader until something reindexes the row.

The decision has to be made where the row is written. A prerender server can
delay a write but never prevent one — answering retryably only spends the
client's retry budget and then the same row lands with a different message, and
the manager prunes a server that answers 5xx, walking its registry as it goes.
So the server states what it knows and the write site acts on it.

The server is the only place holding both tokens at the moment of the render, so
it reaches the conclusion: a missing export that survived a re-render on a pool
that still cannot be shown to have been on the shell being served describes the
environment, not the card. It marks the response and returns the failure
unchanged.

The write site tests for the mark's presence and nothing else. It does not
re-derive the conclusion, so the rule has one implementation rather than two
that drift, and absence means "no verdict" rather than "attributable" — nothing
is withheld by default. When the mark is present and a prior published row
exists, the row keeps the content the last good pass left: `pristine_doc` and
its neighbours were already carried forward there, and this only declines to
stamp `has_error` and `error_doc` over them. The published `search_doc` stays
too, since the error's sparse one describes a render whose result is not being
published.

Two gates keep the suppression from hiding a real break. It requires a prior
published row, because a brand-new card has no good content to protect and
withholding its error would leave nothing at all. And it requires the missing
export to *be* the failure rather than merely appear among the console errors
merged onto it — the broader test is right for driving one more render, where
being wrong costs a render, and wrong for withholding a row, where being wrong
hides a genuine break.

Tests state both directions, since the difference is the whole point: a pool
that never reaches the current shell is marked, a genuine break on a recycled
pool is not, and a timeout that merely mentions a missing export is not.
Substituting the broad predicate for the narrow one fails that last case and
only that case — the first draft of these tests did not distinguish them, which
is why it is there.
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Host Test Results

    1 files  ±0      1 suites  ±0   2h 34m 46s ⏱️ + 26m 50s
4 734 tests +1  4 720 ✅ +1  14 💤 ±0  0 ❌ ±0 
4 749 runs  +1  4 735 ✅ +1  14 💤 ±0  0 ❌ ±0 

Results for commit 31db0f6. ± Comparison against earlier commit 54f6e69.

Realm Server Test Results

    1 files  ± 0    210 suites  +2   1h 12m 30s ⏱️ +34s
2 771 tests +45  2 771 ✅ +45  0 💤 ±0  0 ❌ ±0 
2 810 runs  +45  2 810 ✅ +45  0 💤 ±0  0 ❌ ±0 

Results for commit 31db0f6. ± Comparison against earlier commit 54f6e69.

@backspace
backspace marked this pull request as ready for review September 10, 2026 20:39
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T20:42:49.052044Z 54f6e69 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54f6e69b9c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/runtime-common/index-writer.ts
Comment thread packages/realm-server/prerender/prerender-app.ts Outdated
Two corrections, one of which meant the withholding did nothing in production.

Suppressing `boxel_index.has_error` is not enough to stop the row reading as
errored. `effectiveHasError()` is
`COALESCE(i.has_error, FALSE) OR (ph.error_doc IS NOT NULL AND ph.generation >=
i.generation)`, and `effectiveErrorDoc()` serves `ph.error_doc` in that case —
so a current error on the prerendered-HTML channel publishes the failure
whatever the index channel says. Postgres uses the split channel by default, so
the previous version withheld nothing where it mattered. `writePrerenderedHtmlRow`
now applies the same gate, keeping the preserved render instead of stamping an
error over it, and gated on there being a preserved render for the same reason
the other channel gates on `pristine_doc`.

The verdict also has to say which rows it covers. One visit produces the
instance and file rows independently, and they fail independently: a card render
can hit the stale bundle while the file extraction beside it fails for a reason
of its own. A response-level flag withheld both, hiding that second, genuine
failure. So the mark is now the list of row types whose own failure was the
missing export, and each write site requires its own type to be named. An empty
list is not written at all, because absence has to keep meaning "no verdict"
rather than becoming an empty array a reader might mis-test.

A page that never became usable is the one case that covers both rows: neither
render happened, so the failure belongs to both rather than to one.

Tests follow the scoping. The route case that matters pairs a stale-bundle card
failure with an unrelated file-extract failure and requires the verdict to name
only `instance` — the shape that would have over-suppressed before.
Sign up for free to 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.

1 participant