withastro/astro · error · Error
Astro.locals.runtime.cf has been removed in Astro v6. Use 'A
Error message
Astro.locals.runtime.cf has been removed in Astro v6. Use 'Astro.request.cf' instead.
What it means
Thrown by `@astrojs/cloudflare` (v6+) when user code accesses `Astro.locals.runtime.cf`. The old `runtime.cf` object exposing Cloudflare request properties has been removed; the non-enumerable `runtime` shim's `cf` getter always throws, directing users to `Astro.request.cf` instead.
Source
Thrown at packages/integrations/cloudflare/src/utils/cf-helpers.ts:77
/**
* Creates the Cloudflare-specific locals object with `cfContext`
* and deprecated `runtime` property getters.
*/
export function createLocals(ctx: ExecutionContext): Runtime {
const locals: Runtime = {
cfContext: ctx,
};
Object.defineProperty(locals, 'runtime', {
enumerable: false,
value: {
get env(): never {
throw new Error(
`Astro.locals.runtime.env has been removed in Astro v6. Use 'import { env } from "cloudflare:workers"' instead.`,
);
},
get cf(): never {
throw new Error(
`Astro.locals.runtime.cf has been removed in Astro v6. Use 'Astro.request.cf' instead.`,
);
},
get caches(): never {
throw new Error(
`Astro.locals.runtime.caches has been removed in Astro v6. Use the global 'caches' object instead.`,
);
},
get ctx(): never {
throw new Error(
`Astro.locals.runtime.ctx has been removed in Astro v6. Use 'Astro.locals.cfContext' instead.`,
);
},
},
});
return locals;
}
View on GitHub (pinned to d081033d5f)
Solutions
- Replace `Astro.locals.runtime.cf` with `Astro.request.cf`.
- Search the codebase for `runtime.cf` and `.cf.` patterns to catch all usages.
- Note `Astro.request.cf` is per-request (already populated by Cloudflare), so no extra fetch is needed.
Example fix
// before
export const GET = ({ locals }) => json({ country: locals.runtime.cf.country });
// after
export const GET = ({ request }) => json({ country: request.cf?.country }); Defensive patterns
Strategy: validation
Validate before calling
// Prebuild check for runtime.cf usage.
const { execSync } = require('child_process');
const out = execSync('grep -rn "runtime\\.cf" src/ || true').toString();
if (out) { console.error('Migrate runtime.cf to Astro.request.cf'); process.exit(1); } Prevention
- Migrate all `locals.runtime.cf` to `Astro.request.cf` during the v6 upgrade.
- Treat request geo data as per-request: read from Astro.request, not locals.
- Remember `locals.runtime` is non-enumerable and invisible to console.log.
When it happens
Trigger: Calling `Astro.locals.runtime.cf.country`, `.city`, `.timezone`, etc. in code running under the Cloudflare adapter on Astro v6. Any read of the `cf` property on `locals.runtime` triggers the getter throw.
Common situations: Upgrading a v5 Cloudflare project to v6 that read Geo/IP info from `runtime.cf`. Copy-pasting v5 geo-location tutorial code. The non-enumerable nature of `runtime` hides the property in introspection, obscuring the source.
Related errors
- Astro.locals.runtime.env has been removed in Astro v6. Use '
- Astro.locals.runtime.caches has been removed in Astro v6. Us
- A content collection is defined with legacy features (e.g. m
- LegacyContentConfigError
- `markdown.remarkPlugins`, `markdown.rehypePlugins`, and `mar
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/378d336953a14f6b.
Report an issue: GitHub.