withastro/astro · error · Error
Astro.locals.runtime.cf has been removed in Astro v6. Use…
Error message
Astro.locals.runtime.cf has been removed in Astro v6. Use 'Astro.request.cf' instead.
What it means
Part of the same Astro v6 removal: `Astro.locals.runtime.cf` no longer exists, and the adapter's trap getter throws this message pointing at the replacement. `cf` (request metadata like country, ASN, TLS info) must now be read from `Astro.request.cf`, which Cloudflare populates per request.
Solutions
- Replace `Astro.locals.runtime.cf` with `Astro.request.cf` everywhere.
- Grep for `locals.runtime` to catch the sibling removals (env, caches, ctx) in the same pass.
- Follow the Astro v6 upgrade notes for the Cloudflare adapter.
- Stay on Astro v5 + matching adapter if you cannot migrate yet.
Example fix
// before const country = Astro.locals.runtime.cf.country; // after const country = Astro.request.cf?.country;
Defensive patterns
Strategy: type-guard
Type guard
type LegacyCf = Record<string, unknown> | undefined;
function safeCf(locals: App.Locals, request: Request): LegacyCf {
// Preferred v6 source first
if ('cf' in request && request.cf) return request.cf as LegacyCf;
const runtime = (locals as Record<string, unknown>).runtime;
if (!runtime || typeof runtime !== 'object') return undefined;
try {
return (runtime as { cf: unknown }).cf as LegacyCf;
} catch {
return undefined; // v6 trap — migrate callers to Astro.request.cf
}
} Prevention
- Read request metadata from `Astro.request.cf` — it is the only supported source in v6.
- Codemod `locals.runtime.cf` → `Astro.request.cf?.` (optional-chain, cf can be undefined off-Cloudflare).
- Add `@cloudflare/workers-types` so request.cf is typed during migration.
When it happens
Trigger: In an Astro v6 + @astrojs/cloudflare project, any code accessing `Astro.locals.runtime.cf` (geo checks, bot scoring, locale negotiation) throws as soon as the getter runs.
Common situations: Post-upgrade v5 projects with geo/IP-based routing or analytics code; tutorials written against the old `locals.runtime` API.
Related errors
- Astro.locals.runtime.caches has been removed in Astro v6…
- Astro.locals.runtime.ctx has been removed in Astro v6. Use…
- Astro.locals.runtime.env has been removed in Astro v6. Use…
- LegacyContentConfigError
- A content collection is defined with legacy features (e.g…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/378d336953a14f6b.
Report an issue: GitHub.
Appendix: 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 52e6c34790)