Skip to content

Open binary file URL as a card without 415 or hung spinner#4832

Draft
richardhjtan wants to merge 3 commits into
mainfrom
CS-11147-binary-415-fallback
Draft

Open binary file URL as a card without 415 or hung spinner#4832
richardhjtan wants to merge 3 commits into
mainfrom
CS-11147-binary-415-fallback

Conversation

@richardhjtan
Copy link
Copy Markdown
Contributor

@richardhjtan richardhjtan commented May 14, 2026

Summary

Opening a binary file URL (an uploaded .png, .jpg, …) as a card — by pasting it into the operator-mode URL bar, or via any code path that routes through getCardInstance — fails today: realm-server returns 415 Unsupported Media Type, or the host "Loading card…" spinner hangs with no surfaced error. Three coordinated changes get the file-meta load path taken end-to-end.

Linear: CS-11147

Changes

  1. Realm-server returns file-meta JSON for binary GETs with Accept: application/vnd.card+json instead of 415. Callers can discriminate via data.type === "file-meta". card+markdown on a binary still 415s — markdown can't represent a binary. Touches the three nonJsonFileExists branches in getCard in packages/runtime-common/realm.ts.
  2. Host stack-item infers type:"file" from the URL extension when none is provided. New isFileDefExtension() helper exported from packages/runtime-common/file-def-code-ref.ts, backed by the existing FILEDEF_CODE_REF_BY_EXTENSION map so the set of recognized extensions stays in one place. Pasting a .png URL into the URL bar now takes the file-meta load path from the first request.
  3. Safety net in store.getCardInstance — if anything still asks getCardInstance for a URL that turns out to be a binary, the file-meta JSON is rerouted through getFileMetaInstance and the in-flight card deferred resolves with that result. No hung spinner, no cryptic error.

Files

  • packages/runtime-common/realm.ts
  • packages/runtime-common/file-def-code-ref.ts — new isFileDefExtension export
  • packages/host/app/lib/stack-item.ts
  • packages/host/app/services/store.ts
  • packages/realm-server/tests/card-endpoints-test.ts — asserts file-meta JSON return for card+json on a binary, retains 415 for card+markdown, retains 415 for PATCH/DELETE

Test plan

  • pnpm lint:types green across runtime-common and host (it is).
  • Manual: paste an uploaded .png URL from a realm into a fresh tab. Pre-fix → hang or 415. Post-fix → the FileDef renders as an image.
  • Same URL opened via code-mode → interact: unchanged (already worked because the stack item carried type:"file").
  • Re-run the 7-day staging log classification after deploy; 415-on-binary count drops to ~0.

Out of scope

Other failure modes from the broader broken-image investigation: CS-11144 (auth-SW token race, shipped #4828), CS-11146 (shipped #4829), CS-11145 (regression test in #4830, fix TBD).

🤖 Generated with Claude Code

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts realm card read handling so GET requests for non-JSON files made with card-oriented Accept headers can fall through to the normal file-serving path instead of returning 415.

Changes:

  • Routes missing card JSON index entries for existing non-JSON files through fallbackHandle.
  • Applies the same fallback behavior to card markdown reads.
  • Leaves write/delete card handlers unchanged for binary files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/runtime-common/realm.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Preview deployments

Host Test Results

    1 files  ±  0      1 suites  ±0   1h 30m 56s ⏱️ + 6m 28s
2 665 tests +120  2 649 ✅ +120  15 💤 ±0  0 ❌ ±0  1 🔥 ±0 
2 684 runs  +121  2 667 ✅ +121  15 💤 ±0  1 ❌ ±0  1 🔥 ±0 

Results for commit 3a5e473. ± Comparison against earlier commit 85303ec.

For more details on these errors, see this check.

Realm Server Test Results

    1 files  ± 0      1 suites  ±0   8m 26s ⏱️ -48s
1 410 tests +29  1 409 ✅ +29  0 💤 ±0  1 ❌ ±0 
1 497 runs  +35  1 496 ✅ +35  0 💤 ±0  1 ❌ ±0 

Results for commit 3a5e473. ± Comparison against earlier commit 85303ec.

For more details on these errors, see this check.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread packages/runtime-common/realm.ts Outdated
Comment thread packages/runtime-common/realm.ts Outdated
@richardhjtan richardhjtan force-pushed the CS-11147-binary-415-fallback branch from a54b7f5 to 5668884 Compare May 18, 2026 03:34
@richardhjtan richardhjtan changed the title Realm: GET binary file with card Accept falls through to file handler Open binary file URL as a card without 415 or hung spinner May 18, 2026
richardhjtan and others added 3 commits May 19, 2026 14:00
…handler

A GET request with Accept: application/vnd.card+json (or
.card+markdown) targeting a path that holds a non-JSON file
(typically an uploaded binary like .png) used to return 415
Unsupported Media Type. Callers that produced this mismatch
ended up with a broken image / unusable response.

Route these through fallbackHandle, which serves the file with
inferContentType(...) on the response. Read-only handlers only:
PATCH (3910) and DELETE (4507) still 415 because writing or
deleting a binary as a card is genuinely wrong.

CS-11147

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing regression test asserted GET /greeting.txt with
Accept: application/vnd.card+json returned 415. After the fallback
change, GET should serve the file with its native content-type
instead. Splits the test in two: GET is the new positive case;
PATCH/DELETE still 415.

CS-11147

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A stack item opened directly from the URL bar (no `type:"file"` in the
operator state) defaulted to `type:"card"` and dispatched through
getCardInstance. For an uploaded binary (e.g. `.png`) the realm-server
now returns a file-meta JSON document — getCardInstance rejected it as
"non card document" and the spinner hung on "Loading card...".

Two changes:

- runtime-common: export `isFileDefExtension(filenameOrPath)`, backed
  by the existing FILEDEF_CODE_REF_BY_EXTENSION map so the set of
  recognized extensions stays in one place.
- host stack-item: when no explicit type is provided, infer
  `type:"file"` from the id via `isFileDefExtension`. Pasted-URL opens
  of `.png` / `.svg` / `.gts` / etc. now go through the file-meta load
  path from the start.

Also adds a safety net in store.getCardInstance: if a caller still
manages to invoke it with a binary URL, the file-meta JSON response is
rerouted through getFileMetaInstance instead of throwing a confusing
"non card document" error.

CS-11147

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@richardhjtan richardhjtan force-pushed the CS-11147-binary-415-fallback branch from 85303ec to 3a5e473 Compare May 19, 2026 06:00
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