withastro/astro · warning

context.csp was used when rendering the route ${colors.green

Error message

context.csp was used when rendering the route ${colors.green(state.routeData!.route)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/configuration-reference/#securitycsp

What it means

context.csp (Astro.csp) only exists when security.csp is configured in astro.config. Reading it when this.manifest.csp is absent returns undefined, and in production runtime mode it also logs this warning pointing at the docs — resource/hash injection cannot work because no CSP policy exists. Dev mode returns undefined silently.

Source

Thrown at packages/astro/src/core/fetch/fetch-state.ts:664

		if (this.manifest.adapterName) {
			throw new AstroError({
				...AstroErrorData.ClientAddressNotAvailable,
				message: AstroErrorData.ClientAddressNotAvailable.message(this.manifest.adapterName),
			});
		}

		throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
	}

	getCookies(): AstroCookies {
		return this.cookies;
	}

	getCsp(): APIContext['csp'] {
		const state = this;
		if (!this.manifest.csp) {
			if (getEnvironment(this.manifest).runtimeMode === 'production') {
				this.logger.warn(
					'csp',
					`context.csp was used when rendering the route ${colors.green(state.routeData!.route)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/configuration-reference/#securitycsp`,
				);
			}
			return undefined;
		}
		// Dedupe fallback warnings to once per family+kind for the lifetime of this request.
		const warnedFallback = new Set<string>();
		const warnFallback = (family: 'script' | 'style', kind: CspKind) => {
			if (kind === 'default' || !state.result) {
				return;
			}
			const directive =
				family === 'script' ? state.result.scriptDirective : state.result.styleDirective;
			// Astro's element hashes are folded into the `-elem` directive automatically, so the
			// footgun is specifically user-provided `default`-kind resources on the general directive,
			// which do NOT carry over to the more specific directive.
			const defaultResources = directive.resources

View on GitHub (pinned to e294953aa8)

Solutions

  1. Enable CSP in astro.config: security: { csp: { algorithm: 'sha256', scriptDirective: {...}, styleDirective: {...} } } (or csp: true for defaults)
  2. Or guard the call site: `if (Astro.csp) { ... }` where CSP support is optional
  3. Verify you edited the config that applies to the environment where the warning appears (production runtime)

Example fix

// before — astro.config.mjs with no security.csp, but routes use Astro.csp
export default defineConfig({});

// after
export default defineConfig({
  security: {
    csp: {
      algorithm: 'sha256',
      scriptDirective: { resources: [{ value: "'self'" }] },
    },
  },
});
Defensive patterns

Strategy: type-guard

Validate before calling

// CI: code touching Astro.csp requires security.csp in the config
import config from './astro.config.mjs';
if (!config.security?.csp && usesCspApi) {
  throw new Error('security.csp must be configured before using Astro.csp');
}

Type guard

// Astro.csp is undefined when security.csp is not configured
const csp = Astro.csp;
if (csp) {
  // safe: CSP is configured
  csp.insertDirective(/* ... */);
}

Prevention

When it happens

Trigger: Route or middleware code accesses Astro.csp / context.csp (e.g. to add script or style resources) while astro.config has no security.csp block, or security.csp is left at its default false.

Common situations: Copy-pasting CSP helper code before enabling the feature; a typo placing `csp` at the config top level instead of under `security`; environment-divergent configs where CSP is only set for one environment.

Related errors


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