withastro/astro · error · AstroError
MiddlewareNoDataOrNextCalled
MiddlewareNoDataOrNextCalled
Error message
Make sure your middleware returns a `Response` object, either directly or by returning the `Response` from calling the `next` function.
What it means
Thrown when middleware neither called next() nor returned any value. A middleware must do at least one: call next() to delegate to the next handler/page, or return a Response. Returning undefined without calling next leaves Astro with nothing to render.
Source
Thrown at packages/astro/src/core/middleware/callMiddleware.ts:96
return value;
} else {
/**
* Here we handle the case where `next` was called and returned nothing.
*/
if (responseFunctionPromise) {
return responseFunctionPromise;
} else {
throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
}
}
} else if (typeof value === 'undefined') {
/**
* There might be cases where `next` isn't called and the middleware **must** return
* something.
*
* If not thing is returned, then we raise an Astro error.
*/
throw new AstroError(AstroErrorData.MiddlewareNoDataOrNextCalled);
} else if (value instanceof Response === false) {
throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
} else {
// Middleware did not call resolve and returned a value
return value;
}
});
}
View on GitHub (pinned to d081033d5f)
Solutions
- End every middleware with `return next()` unless intentionally returning a Response.
- Audit conditional branches to ensure each path either returns a Response or calls next.
- Use defineMiddleware() so TypeScript guides the return type.
Example fix
// before
export const onRequest = async (ctx, next) => {
ctx.locals.time = Date.now();
};
// after
export const onRequest = async (ctx, next) => {
ctx.locals.time = Date.now();
return next();
}; Defensive patterns
Strategy: validation
Validate before calling
// Every code path must call next() or return a Response.
export const onRequest = async (ctx, next) => {
ctx.locals.t = Date.now();
return next(); // mandatory terminator
}; Type guard
// Middleware must yield a Response or delegate via next.
function middlewareTerminates(value: unknown, nextCalled: boolean): boolean {
return nextCalled || value instanceof Response;
} Try / catch
try {
await callMiddleware(handler, ctx, render);
} catch (e) {
if (e instanceof Error && /returns a .Response./i.test(e.message)) {
// middleware forgot to return next(); add it
}
throw e;
} Prevention
- End every middleware branch with `return next()` unless returning a Response.
- Audit conditional branches for missing terminators.
- Type middleware handlers with MiddlewareHandler to surface gaps.
When it happens
Trigger: A middleware that does work (sets locals, logs) and ends without `return next()` or any return statement. The `else if (typeof value === 'undefined')` branch at line 96 of callMiddleware.ts catches this.
Common situations: Forgetting to add `return next()` after early logic; a conditional branch that forgets to call next in the fall-through case; refactoring a handler and dropping the final next call.
Related errors
- ResponseSentError
- MiddlewareNotAResponse
- StaticClientAddressNotAvailable
- ForbiddenRewrite
- RedirectWithNoLocation
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/3bb59f3bf6da7839.
Report an issue: GitHub.