vercel/next.js · error · DecodeError
failed to decode param
Error message
failed to decode param
What it means
Thrown as a DecodeError when decodeURIComponent fails on any path segment of a requested page bundle. The webpack hot reloader splits the bundle URL into params and decodeURIComponent-maps each segment; a malformed percent-encoding sequence (e.g. a lone '%' or incomplete multibyte escape) makes decodeURIComponent throw, which is converted into DecodeError('failed to decode param'). This breaks serving that particular page bundle in dev.
Source
Thrown at packages/next/src/server/dev/hot-reloader-webpack.ts:384
// and then the bundle will be served like usual by the actual route in server/index.js
const handlePageBundleRequest = async (
pageBundleRes: ServerResponse,
parsedPageBundleUrl: UrlObject
): Promise<{ finished?: true }> => {
const { pathname } = parsedPageBundleUrl
if (!pathname) return {}
const params = matchNextPageBundleRequest(pathname)
if (!params) return {}
let decodedPagePath: string
try {
decodedPagePath = `/${params.path
.map((param: string) => decodeURIComponent(param))
.join('/')}`
} catch (_) {
throw new DecodeError('failed to decode param')
}
const page = denormalizePagePath(decodedPagePath)
if (page === '/_error' || BLOCKED_PAGES.indexOf(page) === -1) {
try {
await this.ensurePage({ page, clientOnly: true, url: req.url })
} catch (error) {
return await renderScriptError(pageBundleRes, getProperError(error))
}
const errors = await this.getCompilationErrors(page)
if (errors.length > 0) {
return await renderScriptError(pageBundleRes, errors[0], {
verbose: false,
})
}
}View on GitHub (pinned to 0ae8c72462)
Solutions
- Inspect the failing request URL (server logs) for stray '%' or truncated escape sequences and fix the client/proxy generating it.
- If a reverse proxy is re-encoding the path, configure it to pass URLs through unchanged.
- Use URL-encoding-safe page names (avoid special characters in page filenames).
- Reproduce with curl using the exact URL to confirm the malformed segment, then correct the source of the request.
Example fix
# before (malformed percent escape) curl '/_next/static/dev/pages/%E0%A4.js' # after (properly encoded path) curl '/_next/static/dev/pages/about.js'
Defensive patterns
Strategy: try-catch
Validate before calling
// Reject malformed percent-encoding before it reaches the page-bundle handler
function isSafeEncodedPath(segments: string[]): boolean {
for (const seg of segments) {
try { decodeURIComponent(seg) } catch { return false }
}
return true
} Try / catch
try {
decodedPagePath = '/' + params.path.map((p: string) => decodeURIComponent(p)).join('/')
} catch {
throw new DecodeError('failed to decode param')
} Prevention
- Don't generate internal _next URLs client-side; let Next.js emit them.
- Configure reverse proxies to forward paths verbatim (no double-encoding).
- Use encodeURIComponent consistently if you must construct such URLs.
When it happens
Trigger: A request to /_next/static/<buildid>/pages/<segments>.js where one segment contains an invalid percent-encoded sequence such as '%zz', '%E0%A4', or a raw percent sign. decodeURIComponent throws and is caught and rethrown as DecodeError.
Common situations: A proxy/CDN rewrites or truncates URLs, producing broken percent escapes. A bot or scanner requests a malformed _next path. A route/page name contains characters that get mis-encoded by a reverse proxy. Custom middleware that rewrites the URL incorrectly.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${sourceURL}: Invalid source map. Only conformant source map
- Failed to decode path param(s).
- Dev server did not become ready within ${timeoutMs}ms
- Each route must start with '/': ${route}
- Failed to fetch _devPagesManifest.json. Is something blockin
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/ff268879aa2ad684.
Report an issue: GitHub.