Skip to content

fix(cf-function): guard against null metadata to prevent 502s#6849

Open
nicholasgubbins wants to merge 1 commit into
anomalyco:devfrom
nicholasgubbins:fix/cf-function-metadata-null-guard
Open

fix(cf-function): guard against null metadata to prevent 502s#6849
nicholasgubbins wants to merge 1 commit into
anomalyco:devfrom
nicholasgubbins:fix/cf-function-metadata-null-guard

Conversation

@nicholasgubbins
Copy link
Copy Markdown
Contributor

Summary

  • When the KV store returns null/undefined for the metadata key — which can happen transiently as the KV entry propagates to edge nodes after a deployment — routeSite throws an uncaught TypeError accessing metadata.base, causing CloudFront to return a 502.
  • The same guard is applied to both static-site.ts and ssr-site.ts.
  • The fix fails open: if metadata is unavailable, the request is passed through to the default origin unchanged rather than crashing.

Root cause

The issue is most visible when errorPage is configured on a StaticSite. When errorPage is set, SST stores errorResponseCode: 404 in the KV metadata and omits custom404, disabling the function-level SPA fallback in favour of distribution-level customErrorResponses. This means unmatched requests go through an extra round-trip (original request → S3 403 → CloudFront fetches error page → function invoked again), doubling the exposure to the KV propagation window and making the 502 appear inconsistently depending on which edge node handles the request.

Test plan

  • Deploy a StaticSite with errorPage set, request a non-existent path — should return 404 with the error page, not 502
  • Simulate a missing metadata key (e.g. delete the KV entry temporarily) — should pass through to origin rather than 502

🤖 Generated with Claude Code

When the KV store returns null/undefined for the metadata key — which
can happen transiently during deployment as the KV entry propagates to
edge nodes — routeSite throws an uncaught TypeError accessing
metadata.base, causing CloudFront to return a 502.

This is most visible when errorPage is configured, because that disables
the function-level custom404 fallback in favour of distribution-level
customErrorResponses. The 502 manifests inconsistently because only
some edge nodes are affected during the propagation window.

The fix fails open: if metadata is unavailable, pass the request through
to the default origin unchanged rather than crashing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nicholasgubbins nicholasgubbins force-pushed the fix/cf-function-metadata-null-guard branch from 7ae7cfd to 7ed9da2 Compare May 1, 2026 08:04
@nicholasgubbins
Copy link
Copy Markdown
Contributor Author

  1. You request a non-existent path
  2. Function runs → KV lookup succeeds → sets S3 origin → S3 returns 403/404
  3. CloudFront's customErrorResponses fires → second function invocation for /404.html
  4. That second invocation hits a cold edge that hasn't cached the routing metadata yet → KV read fails → returns event.request →
    placeholder.sst.dev → 502

The second invocation is essentially always a "fresh" request from CloudFront's perspective — it's not the same cache key as the original
request, so it bypasses whatever warming the edge node had. Valid pages don't go through this second invocation at all, so you only see
the cold-edge failure on 404s.

@nicholasgubbins
Copy link
Copy Markdown
Contributor Author

this is the issue i faced yesterday with #6848

Copy link
Copy Markdown
Collaborator

@vimtor vimtor left a comment

Choose a reason for hiding this comment

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

i don’t think this fully fixes the 502. when metadata is missing, returning event.request still sends the request to the default origin, which is placeholder.sst.dev

for standalone sites, that origin does not resolve, so CloudFront still returns 502 Failed to contact the origin instead of the intended site/error response

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