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

  1. Replace `Astro.locals.runtime.cf` with `Astro.request.cf`.
  2. Search the codebase for `runtime.cf` and `.cf.` patterns to catch all usages.
  3. 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

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


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/378d336953a14f6b. Report an issue: GitHub.