withastro/astro · warning
Usage of `vercel-edge-middleware.js` is deprecated. You can
Error message
Usage of `vercel-edge-middleware.js` is deprecated. You can now use the `waitUntil(promise)` function directly as `ctx.locals.waitUntil(promise)`.
What it means
When @astrojs/vercel generates its edge middleware bundle, generateEdgeMiddleware checks for a `vercel-edge-middleware.js` (or `.ts`) file in your `srcDir` (packages/integrations/vercel/src/index.ts:62 defines the name; the check is at serverless/middleware.ts:106). If the file exists, the adapter warns that this hook is deprecated and still wires it into the generated middleware (`import handler ...` / `await handler({ request, context })`). The replacement is calling `ctx.locals.waitUntil(promise)` (surfaced as `waitUntil` inside Astro middleware) instead of a separate edge-middleware entry file.
Source
Thrown at packages/integrations/vercel/src/serverless/middleware.ts:120
}
return pathToFileURL(bundledFilePath);
}
function edgeMiddlewareTemplate(
astroMiddlewareEntryPointPath: URL,
vercelEdgeMiddlewareHandlerPath: URL,
middlewareSecret: string,
logger: AstroIntegrationLogger,
isrForwarding?: IsrForwarding,
) {
const middlewarePath = JSON.stringify(
fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/'),
);
const filePathEdgeMiddleware = fileURLToPath(vercelEdgeMiddlewareHandlerPath);
let handlerTemplateImport = '';
let handlerTemplateCall = '{}';
if (existsSync(filePathEdgeMiddleware + '.js') || existsSync(filePathEdgeMiddleware + '.ts')) {
logger.warn(
'Usage of `vercel-edge-middleware.js` is deprecated. You can now use the `waitUntil(promise)` function directly as `ctx.locals.waitUntil(promise)`.',
);
const stringified = JSON.stringify(filePathEdgeMiddleware.replace(/\\/g, '/'));
handlerTemplateImport = `import handler from ${stringified}`;
handlerTemplateCall = `await handler({ request, context })`;
} else {
}
return `
${handlerTemplateImport}
import { onRequest } from ${middlewarePath};
import { createContext, trySerializeLocals } from 'astro/middleware';
const isrRoutes = ${JSON.stringify(isrForwarding?.isrRoutes ?? [])}.map((source) => new RegExp(source));
const isrExcludedRoutes = ${JSON.stringify(isrForwarding?.isrExcludedRoutes ?? [])}.map(
(source) => new RegExp(source),
);
const isCached = (pathname) =>View on GitHub (pinned to 3578d45d34)
Solutions
- Delete `src/vercel-edge-middleware.js` (or `.ts`) and move its logic into your Astro middleware (`src/middleware.ts`), replacing `context.waitUntil(...)` calls with `ctx.locals.waitUntil(...)` inside `onRequest`.
- Verify no other code imports `vercel-edge-middleware` before deleting (search the repo for the filename).
- Rebuild and confirm the warning is gone and deferred work (e.g. analytics flushing, cache revalidation) still completes by checking function logs on Vercel.
Example fix
// before: src/vercel-edge-middleware.js
export default async function ({ request, context }) {
context.waitUntil(fetch('https://example.com/collect', { method: 'POST', body: request.url }));
}
// after: src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware((ctx, next) => {
ctx.locals.waitUntil(
fetch('https://example.com/collect', { method: 'POST', body: ctx.url.toString() })
);
return next();
}); Defensive patterns
Strategy: validation
Validate before calling
// abort before build if the deprecated edge middleware file still exists
import fs from 'node:fs';
import path from 'node:path';
const legacy = ['vercel-edge-middleware.js', 'vercel-edge-middleware.ts'].map((f) =>
path.join('src', f)
);
const found = legacy.filter((f) => fs.existsSync(f));
if (found.length) {
throw new Error(`Deprecated ${found.join(', ')} found — migrate to ctx.locals.waitUntil in src/middleware.ts`);
} Prevention
- When adding deferred work in Vercel middleware, always use `ctx.locals.waitUntil(promise)` inside `src/middleware.ts` — never add a `src/vercel-edge-middleware.js` file.
- Search the project for `vercel-edge-middleware` after every @astrojs/vercel major upgrade; deprecation warnings in this adapter precede removal.
- Codify the existence check in a repo lint script or CI step so a legacy file re-added from an old template fails the build.
When it happens
Trigger: Building any Astro project with the Vercel adapter in serverless mode (middleware enabled) while `src/vercel-edge-middleware.js` or `src/vercel-edge-middleware.ts` exists in the source directory. The warning is emitted from edgeMiddlewareTemplate during `astro build`; the legacy file continues to work and is imported into the generated `middleware.mjs`.
Common situations: Projects created from older Vercel/Astro templates or docs that instructed adding `src/vercel-edge-middleware.js` to defer work with `waitUntil`; upgrading @astrojs/vercel past the release that added native `waitUntil` support without migrating the legacy file; copying a middleware setup from an outdated blog post or example repo.
Related errors
- Your project is being built for Node.js ${major} as the runt
- Your project is being built for Node.js ${major} as the ru
- Your project is being built for Node.js ${major} as the runt
- Auto-generating collections for folders in "src/content/" t
- MiddlewareNotAResponse
AI-assisted analysis of withastro/astro@3578d45d34 (2026-08-18).
Data as JSON: /api/errors/0738c42f46be5138.
Report an issue: GitHub.