withastro/astro · error · Error

Astro.locals.runtime.caches has been removed in Astro v6. Us

Error message

Astro.locals.runtime.caches has been removed in Astro v6. Use the global 'caches' object instead.

What it means

Thrown by `@astrojs/cloudflare` (v6+) when user code accesses `Astro.locals.runtime.caches`. The old `runtime.caches` (the Cloudflare Cache API) has been removed from the locals shim; the non-enumerable `runtime` property's `caches` getter always throws, directing users to the global `caches` object instead.

Source

Thrown at packages/integrations/cloudflare/src/utils/cf-helpers.ts:82

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;
}

/**
 * Extracts the client IP address from the `cf-connecting-ip` header.
 */
export function getClientAddress(request: Request): string | undefined {
	return getValidatedIpFromHeader(request.headers.get('cf-connecting-ip'));

View on GitHub (pinned to d081033d5f)

Solutions

  1. Replace `Astro.locals.runtime.caches` with the global `caches` (already in scope in the worker).
  2. Search for `runtime.caches` across the project.
  3. Confirm `caches` global typing is available (provided by `@cloudflare/workers-types`).

Example fix

// before
export const GET = async ({ locals }) => {
  const cache = locals.runtime.caches.default;
  return cache.match(new Request('https://example.com'));
};

// after
export const GET = async () => {
  const cache = caches.default;
  return cache.match(new Request('https://example.com'));
};
Defensive patterns

Strategy: validation

Validate before calling

// Prebuild check for runtime.caches usage.
const { execSync } = require('child_process');
const out = execSync('grep -rn "runtime\\.caches" src/ || true').toString();
if (out) { console.error('Migrate runtime.caches to global caches'); process.exit(1); }

Prevention

When it happens

Trigger: Calling `Astro.locals.runtime.caches.default.match(...)` or `runtime.caches.open(...)` in a worker under the Cloudflare adapter on Astro v6. Any read of `caches` on `locals.runtime` triggers the throw.

Common situations: Upgrading a v5 project that used edge caching via `runtime.caches`. Copy-pasting v5 caching examples. The global `caches` is already available in the worker runtime, so the locals indirection was redundant and is now removed.

Related errors


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