Skip to content

fix(server): say why a storage serve fell back, not just what failed - #1094

Merged
housejester merged 3 commits into
mainfrom
jde/serve-fallback-reason
Sep 3, 2026
Merged

housejester merged 3 commits into
mainfrom
jde/serve-fallback-reason

Conversation

@housejester

Copy link
Copy Markdown
Collaborator

When a storage= query cannot compile against the serve shape, Publisher serves live and logs the compiler's error. That error names the symbol it could not resolve — a symptom shared by the two quite different reasons a source can be absent from the shape:

  • it carries no #@ persist, so it was never materialized
  • it is materialized, and the freshness gate withheld it for this query

Both print Reference to undefined object 'x'. Nothing downstream distinguishes them, and neither is recoverable from the package definition afterwards — the fresh subset is computed per query.

What this changes

Two fields on the existing line. No behaviour change, no new log.

storage serve-shape ineligible for this query; serving live
  error:         Reference to undefined object 'traffic_by_product'
  shapeSources:  [_traffic_by_product_fact, _reviews_by_product_fact, …]
  staleSources:  []

Nothing stale, and the wanted name is in neither set → it is not materialized. The #@ persist is on a different source than the one being queried.

storage serve-shape ineligible for this query; serving live
  error:         Reference to undefined object 'storage_rollup'
  shapeSources:  [storage_stats]
  staleSources:  [storage_rollup]

Bound, withheld, serving live because that is what its freshness fallback asks for. Working exactly as configured.

Why it is worth the two fields

Both messages above are real, from one afternoon on one deployment. Two engineers read the first as a serve-path regression and the second as the same bug; they are unrelated, and one of them is not a bug at all. Reaching that took reading the binding set off a live pod and running probe queries against individual sources — the log alone could not separate "the model does not say what you think" from "the table is older than you think".

The sets are free at that point: serveBindings is the package's, freshServeBindings was just computed for the gate.

Shape

The set computation is a pure exported function, serveShapeDiagnostics, rather than inline in the catch — so the tests exercise the code the caller runs instead of a copy of its logic. Both fields are mutation-checked: pinning staleSources to [] (the pre-change state) and widening shapeSources to all bindings each turn the same two assertions red.

The pair is asserted together in one test on purpose. Either field alone still leaves the two failures indistinguishable, which is the state this replaces.

bun test src/service — 2473 pass, 0 fail. tsc --noEmit and eslint clean.

James Estes and others added 2 commits August 31, 2026 12:21
The fallback logged the compiler's error, which names the symbol it could not
resolve. That symptom is shared by both reasons a source is missing from the
serve shape -- it carries no `#@ persist`, or the freshness gate withheld it --
so "Reference to undefined object 'x'" reads identically whether the model is
wrong or the table is merely stale, and neither is recoverable from the package
definition after the fact.

Both sets are already known at that point. Report them: `shapeSources` is what
the shape offered, `staleSources` is what was bound and withheld. A name the
query wants that appears in neither is not materialized at all.

Signed-off-by: James Estes <james.estes@credibledata.com>
@housejester
housejester enabled auto-merge (squash) September 3, 2026 15:09
@housejester
housejester merged commit fd6d964 into main Sep 3, 2026
14 checks passed
@housejester
housejester deleted the jde/serve-fallback-reason branch September 3, 2026 15:33
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.

2 participants