Skip to content

Cloudflare adapter (Astro 6): /api/keystatic/* crashes with 'Astro.locals.runtime.env has been removed in Astro v6' #1554

Description

@peppir

Summary

With @astrojs/cloudflare on Astro 6, @keystatic/astro's GitHub-mode API routes
(/api/keystatic/*, e.g. github/login) crash at runtime with:

Error: Astro.locals.runtime.env has been removed in Astro v6. Use 'import { env } from "cloudflare:workers"' instead.
    at get env (chunks/worker-entry_....mjs:19512:15)
    at Module.keystaticAPIRoute (chunks/keystatic-api_....mjs:821:213)
    at renderEndpoint (chunks/worker-entry_....mjs:1053:32)
    at PagesHandler.handle (chunks/worker-entry_....mjs:4259:26)

This reproduces both in astro dev (with the Cloudflare adapter active) and on a real
deployed Cloudflare Worker (captured via wrangler tail). GitHub-mode credentials
(KEYSTATIC_GITHUB_CLIENT_ID/SECRET, KEYSTATIC_SECRET) are correctly configured —
the crash happens once the API handler tries to read the Cloudflare runtime env to get
at those values.

Filed as requested by @emmatown in #1515 ("please open a new issue with ... where the
issue occurs") — this is a different, Cloudflare-specific failure than the
NoMatchingRenderer issue discussed there.

Environment

  • astro: 6.4.8
  • @astrojs/cloudflare: 13.7.0
  • @astrojs/react: 6.0.1
  • @keystatic/astro: 5.1.0
  • @keystatic/core: 0.5.50
  • react / react-dom: 19.2.7
  • wrangler: 4.108.0
  • Storage mode: github

Steps to reproduce

  1. Astro 6 project with output: 'static' + adapter: cloudflare().
  2. Add keystatic() to integrations, with storage: { kind: 'github', repo: ... } in
    keystatic.config.ts and valid KEYSTATIC_GITHUB_CLIENT_ID / _CLIENT_SECRET /
    KEYSTATIC_SECRET env vars.
  3. Run astro dev (or deploy via wrangler deploy) and hit /api/keystatic/github/login
    (or complete the GitHub OAuth flow via /keystatic).
  4. Request fails with the error above (500 in production, similar in dev).

Related prerequisite issue (same setup)

Before reaching the above, wiring keystatic() under @astrojs/cloudflare on Astro 6
also crashes with module is not defined inside react/index.js, because
@astrojs/cloudflare's own SSR/workerd optimizeDeps defaults don't include react/
react-dom, so the raw CJS build reaches workerd unbundled. Adding this to the user's
own vite config works around it (the adapter merges user optimizeDeps.include into
its SSR environment config):

vite: {
  optimizeDeps: {
    include: ['react', 'react-dom', 'react/jsx-runtime', 'react-dom/server', 'react-dom/server.edge'],
  },
},

Mentioning this since it's a prerequisite to even reach the locals.runtime.env crash
above, and other Cloudflare+Astro 6 users will likely hit it first.

Expected behavior

Keystatic's GitHub-mode API handler should read the Cloudflare Workers runtime env via
import { env } from 'cloudflare:workers' (or accept it through its existing
adapter-provided context/locals) instead of the removed Astro.locals.runtime.env,
so GitHub-mode works under Astro 6 + @astrojs/cloudflare.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions