withastro/astro · error · AstroError

OnlyResponseCanBeReturned

OnlyResponseCanBeReturned

Error message

Route `${route}` returned a `${returnedValue}`. Only a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned from Astro files.

What it means

When a page's component factory result is a head+content wrapper (`isHeadAndContent`), Astro expects the wrapper's `.content` to itself be a valid render-template result. If it isn't, the page returned something that is neither a `Response` nor a renderable template, so Astro throws `OnlyResponseCanBeReturned` with the route and the value's type. Pages must return a `Response` (or render normally without returning).

Source

Thrown at packages/astro/src/runtime/server/render/astro/render.ts:323

}

async function callComponentAsTemplateResultOrResponse(
	result: SSRResult,
	componentFactory: AstroComponentFactory,
	props: any,
	children: any,
	route?: RouteData,
) {
	const factoryResult = await componentFactory(result, props, children);

	if (factoryResult instanceof Response) {
		return factoryResult;
	}
	// we check if the component we attempt to render is a head+content
	else if (isHeadAndContent(factoryResult)) {
		// we make sure that content is valid template result
		if (!isRenderTemplateResult(factoryResult.content)) {
			throw new AstroError({
				...AstroErrorData.OnlyResponseCanBeReturned,
				message: AstroErrorData.OnlyResponseCanBeReturned.message(
					route?.route,
					typeof factoryResult,
				),
				location: {
					file: route?.component,
				},
			});
		}

		// return the content
		return factoryResult.content;
	} else if (!isRenderTemplateResult(factoryResult)) {
		throw new AstroError({
			...AstroErrorData.OnlyResponseCanBeReturned,
			message: AstroErrorData.OnlyResponseCanBeReturned.message(route?.route, typeof factoryResult),
			location: {

View on GitHub (pinned to d081033d5f)

Solutions

  1. Do not return arbitrary values from an Astro page; render markup normally or return a `Response`.
  2. To send a redirect or custom status, `return new Response(null, { status, headers })` or `return Astro.redirect(...)`.
  3. If you construct head+content structures manually (integration/plugin), ensure `.content` is a render-template result.

Example fix

// before — page returns a plain object
---
return { html: '<p>hi</p>' };
---

// after — return a Response
---
return new Response('<p>hi</p>', { headers: { 'content-type': 'text/html' } });
---
Defensive patterns

Strategy: validation

Validate before calling

// Ensure page frontmatter only returns a Response (or nothing)
function assertPageReturn(value: unknown): Response | void {
  if (value instanceof Response) return value;
  if (value === undefined) return;
  throw new Error('Astro pages may only return a Response');
}

Type guard

const isPageResponse = (v: unknown): v is Response => v instanceof Response;

Prevention

When it happens

Trigger: A `.astro` page `return`s an object/value that wraps content incorrectly; a manually constructed head+content-like structure with a malformed `.content`; returning a non-Response, non-template value from page frontmatter.

Common situations: Returning a custom object or string from `.astro` frontmatter expecting it to be the response body; interfering with Astro's internal content wrappers via an integration.

Related errors


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