withastro/astro · error

Incomplete request

Error message

Incomplete request

What it means

During `astro dev`, requests first pass through `astroDevPrerenderHandler`, the middleware that renders prerendered routes inside the core dev server. It immediately rejects any request whose `url` is undefined or whose `method` is missing by writing a bare 500 with reason 'Incomplete request'. Node's HTTP parser always populates these fields for well-formed requests, so hitting this guard means the dev server received a degenerate or programmatically forged request rather than a valid HTTP message.

Source

Thrown at packages/astro/src/vite-plugin-astro-server/plugin.ts:144

					route: '',
					handle: trailingSlashMiddleware(settings),
				});
				// Prevent serving files outside srcDir/publicDir (e.g., /README.md at project root)
				viteServer.middlewares.stack.unshift({
					route: '',
					handle: routeGuardMiddleware(settings),
				});
				// Validate Sec-Fetch metadata headers to restrict cross-origin subresource requests
				viteServer.middlewares.stack.unshift({
					route: '',
					handle: secFetchMiddleware(logger, settings.config.security?.allowedDomains),
				});

				if (prerenderHandler && shouldHandlePrerenderInCore) {
					viteServer.middlewares.use(
						async function astroDevPrerenderHandler(request, response, next) {
							if (request.url === undefined || !request.method) {
								response.writeHead(500, 'Incomplete request');
								response.end();
								return;
							}

							if (request.url.startsWith('/@') || request.url.startsWith('/__')) {
								return next();
							}

							if (request.url.includes('/node_modules/')) {
								return next();
							}

							try {
								const pathname = decodeURI(new URL(request.url, 'http://localhost').pathname);
								const { routes } = (await prerenderHandler.environment.runner.import(
									'virtual:astro:routes',
								)) as { routes: RouteInfo[] };
								const routesList = { routes: routes.map((route) => route.routeData) };

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Confirm with a real request: `curl -i http://localhost:4321/` — a well-formed request must never return 'Incomplete request'; if it does, a middleman is mangling it
  2. Identify the client producing malformed traffic on the dev port (probes, scripts, proxies) and stop or fix it
  3. If you inject middleware or drive the stack programmatically, always pass full http.IncomingMessage-shaped objects with `url` and `method` set
  4. Check custom middleware ordering if you mutate `req` before Astro's handlers run

Example fix

// Triggers the guard (raw socket, no request line)
// $ printf 'GARBAGE\r\n\r\n' | nc localhost 4321  -> 500 Incomplete request

// Never triggers it
// $ curl -i http://localhost:4321/
Defensive patterns

Strategy: validation

Validate before calling

// Only for tooling that drives the dev-server middleware stack directly
import type { IncomingMessage } from 'node:http';
function isCompleteRequest(req: Partial<IncomingMessage>): boolean {
  return typeof req.url === 'string' && typeof req.method === 'string' && req.method.length > 0;
}
if (!isCompleteRequest(mockReq)) throw new Error('refusing to forward incomplete request');

Type guard

type CompleteRequest = IncomingMessage & { url: string; method: string };
function isCompleteRequest(req: unknown): req is CompleteRequest {
  const r = req as Partial<IncomingMessage>;
  return typeof r?.url === 'string' && typeof r?.method === 'string' && r.method.length > 0;
}

Prevention

When it happens

Trigger: A raw TCP client connects to the dev port and sends bytes that never form a valid HTTP request line; a proxy, test harness, or script invokes the Vite middleware stack with a mock req object lacking `url`/`method`; load-balancer or port-scanner probes open connections without speaking HTTP.

Common situations: Corporate health checks or vulnerability scanners probing the dev port; custom dev tooling that drives `viteServer.middlewares` directly; hand-rolled socket scripts instead of fetch/curl; upgrading Astro to a version where prerender handling moved into core and this guard appeared.

Related errors


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