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
callMiddleware throws AstroErrorData.MiddlewareNoDataOrNextCalled when the middleware neither called next() nor returned anything. Astro requires exactly one of those two outcomes per request — the middleware must either delegate to the rest of the pipeline or produce a Response itself. This error means some code path fell through doing neither.
Solutions
- Make every branch end in `return next()` or `return <Response>`
- Add a final `return next();` at the bottom of the middleware as a safe default
- Type the middleware with defineMiddleware so return paths are easier to audit; add a unit test hitting the deny path
Example fix
// before — deny path returns undefined
export const onRequest = async (context, next) => {
if (context.cookies.get('session')) return next();
};
// after
export const onRequest = async (context, next) => {
if (!context.cookies.get('session')) return context.redirect('/login', 302);
return next();
}; Defensive patterns
Strategy: validation
Validate before calling
export const onRequest = async (context, next) => {
if (!isAuthorized(context)) return context.redirect('/login', 302); // deny path returns a Response
return next(); // fall-through path delegates
}; Prevention
- End every branch with `return next()` or `return <Response>`
- Add a final `return next();` as the last statement of each middleware
- Write tests for the deny path — it is the branch that usually falls through
When it happens
Trigger: An auth middleware with `if (authorized) return next();` but no else branch; an async middleware whose early return was removed during refactoring; a middleware returning undefined from a conditional block (e.g. inside a switch) on the deny path.
Common situations: Adding conditional logic to existing middleware and forgetting the negative path; renaming or refactoring that drops a `return`; TypeScript not flagging it because the handler type permits undefined at runtime.
Related errors
- `Astro.session` was accessed but no session storage is…
- `context.next` is not implemented for serverless functions
- FetchState not found on APIContext. `next(payload)`…
- ForbiddenRewrite
- Incomplete request
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/3bb59f3bf6da7839.
Report an issue: GitHub.
Appendix: 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 52e6c34790)