withastro/astro · error · AstroError
CacheNotEnabled
CacheNotEnabled
Error message
`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `cache`.
What it means
Astro.cache is backed by a provider supplied either by an adapter or by the cache config. The runtime object exists even without a provider, but cache operations — invalidate() here — throw CacheNotEnabled when no provider is configured, which is also the case in dev where caching is disabled and a noop runtime is installed.
Solutions
- Configure a provider in astro.config: cache: { provider: '...' }, or use an adapter that ships a default cache provider.
- Guard every call with the enabled flag: if (Astro.cache.enabled) { ... } — the interface exposes it for exactly this check.
- In dev, treat caching as a no-op and skip invalidation logic, or verify behavior in a preview/build run where the provider is active.
Example fix
// before
await Astro.cache.invalidate({ tags: ['posts'] });
// after
if (Astro.cache.enabled) {
await Astro.cache.invalidate({ tags: ['posts'] });
}
// and enable the feature in astro.config.mjs:
// export default defineConfig({ cache: { provider: '...' } }); Defensive patterns
Strategy: type-guard
Validate before calling
// Gate every cache interaction on the runtime flag
if (Astro.cache.enabled) {
await Astro.cache.invalidate({ tags: ['posts'] });
} else {
// dev or provider-less deploy: caching is a no-op here
} Type guard
const canInvalidate = (cache: { enabled: boolean }): boolean => cache.enabled;
// usage
if (canInvalidate(Astro.cache)) await Astro.cache.invalidate({ tags }); Prevention
- Check Astro.cache.enabled (or context.cache.enabled) before any cache call — libraries are expected to.
- Configure cache: { provider: ... } in astro.config or rely on an adapter that provides one.
- Verify cache behavior in preview/production runs; dev intentionally runs without a provider.
When it happens
Trigger: Calling Astro.cache.invalidate(...) or context.cache.invalidate(...) without cache: { provider: ... } in astro.config and without an adapter that injects a default provider; using any cache method during astro dev, where the noop runtime is active.
Common situations: Testing cache invalidation locally in dev; deploying with the static adapter (no cache provider) while the code assumes the node adapter's cache; enabling cache-related code paths before wiring the cache config.
Related errors
- `cache.set()` was called but caching is not enabled…
- CacheNotEnabled
- CacheProviderNotFound
- CacheQueryConfigConflict
- SessionStorageInitError
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/9a4fc7d7842acef0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/cache/runtime/cache.ts:103
get tags(): string[] {
return [...this.#tags];
}
/**
* Get the current cache options (read-only snapshot).
* Includes all accumulated options: maxAge, swr, tags, etag, lastModified.
*/
get options(): Readonly<CacheOptions> {
return {
...this.#options,
tags: this.tags,
};
}
async invalidate(input: InvalidateOptions | LiveDataEntry): Promise<void> {
if (!this.#provider) {
throw new AstroError(CacheNotEnabled);
}
let options: InvalidateOptions;
if (isLiveDataEntry(input)) {
options = { tags: input.cacheHint?.tags ?? [] };
} else {
options = input;
}
return this.#provider.invalidate(options);
}
/** @internal */
[APPLY_HEADERS](response: Response, request: Request): void {
if (this.#disabled) return;
const finalOptions: CacheOptions = { ...this.#options, tags: this.tags };
if (finalOptions.maxAge === undefined && !finalOptions.tags?.length) return;
const headers =
this.#provider?.setHeaders?.(finalOptions, request) ?? defaultSetHeaders(finalOptions);View on GitHub (pinned to e294953aa8)