Skip to content

Realm: GET binary file with card Accept falls through to file handler#4832

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

Realm: GET binary file with card Accept falls through to file handler#4832
richardhjtan wants to merge 2 commits into
mainfrom
CS-11147-binary-415-fallback

Conversation

@richardhjtan
Copy link
Copy Markdown
Contributor

Summary

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 a .png) used to return 415 Unsupported Media Type. Callers ended up with a broken response.

Route those through fallbackHandle, which serves the file with inferContentType(...) as the content-type. Read-only handlers only — PATCH and DELETE on a binary still return 415 because writing or deleting a binary as a card is genuinely wrong.

Part of a broader broken-image investigation. Full report shared separately.

Linear: CS-11147

What this fixes

When an internal caller mis-routes a binary file URL through a card-JSON or card-markdown pipeline (e.g. a host code path that lazily resolves a relationship and assumes the target is a card), the realm-server previously returned 415. The caller had no graceful path back to the bytes. Falling through to the file handler returns the binary with its native content-type, so any caller that inspects content-type can decide what to do, and any caller that just wants the bytes is unblocked.

This is a server-side leniency change, not a behavior change for legitimate card requests — the fallback only fires when an index entry does not exist and the path holds a non-JSON file.

Files

  • packages/runtime-common/realm.ts — three 415 → fallback edits in the getCardJson (ETag fast path + main path) and getCardMarkdown handlers.

Test plan

  • pnpm lint:types green (it is).
  • Hit curl -H 'Accept: application/vnd.card+json' <realm>/path/to/foo.png against staging post-deploy; expect 200 with Content-Type: image/png and the binary body. Pre-fix returned 415.
  • 7 days post-deploy, re-run the staging log scan for 415s on image URLs. Count should drop to ~0.

Out of scope

Other failure modes from the same investigation: CS-11144 (shipped #4828), CS-11146 (shipped #4829), CS-11145 (regression test in #4830, fix still TBD).

🤖 Generated with Claude Code

…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>
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

Host Test Results

    1 files  ±0      1 suites  ±0   1h 27m 23s ⏱️ - 17m 7s
2 659 tests  - 2  2 644 ✅  - 2  15 💤 ±0  0 ❌ ±0 
2 678 runs   - 2  2 663 ✅  - 2  15 💤 ±0  0 ❌ ±0 

Results for commit 5668884. ± Comparison against earlier commit a54b7f5.

Realm Server Test Results

    1 files  ± 0      1 suites  ±0   9m 26s ⏱️ - 1m 24s
1 379 tests +13  1 378 ✅ +12  0 💤 ±0  1 ❌ +1 
1 460 runs  +15  1 459 ✅ +14  0 💤 ±0  1 ❌ +1 

Results for commit 5668884. ± Comparison against earlier commit a54b7f5.

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
if (!entry) {
if (await this.nonJsonFileExists(localPath)) {
return unsupportedMediaType(request, requestContext);
return this.fallbackHandle(request, requestContext);
Comment thread packages/runtime-common/realm.ts Outdated
if (instanceEntry === undefined) {
if (await this.nonJsonFileExists(localPath)) {
return unsupportedMediaType(request, requestContext);
return this.fallbackHandle(request, requestContext);
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>
@richardhjtan richardhjtan force-pushed the CS-11147-binary-415-fallback branch from a54b7f5 to 5668884 Compare May 18, 2026 03:34
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