sveltejs/kit · error · Error
Async param matchers are not supported
Error message
Async param matchers are not supported
What it means
Param matchers in SvelteKit use the Standard Schema `validate` API. `run_matcher` requires validation to be synchronous; if a matcher's `~standard.validate` returns a Promise (async validation), routing cannot proceed because param matching happens synchronously during route resolution. The library therefore rejects async matchers outright.
Source
Thrown at packages/kit/src/utils/routing.js:147
* don't affect the path (i.e. groups). The root route is represented by `/`
* and will be returned as `['']`.
* @param {string} route
* @returns string[]
*/
export function get_route_segments(route) {
return route.slice(1).split('/').filter(affects_path);
}
/**
* @param {ParamMatcher} matcher
* @param {string} value
* @returns {{ success: true, value: any } | { success: false }}
*/
function run_matcher(matcher, value) {
const result = matcher['~standard'].validate(value);
if (result instanceof Promise) {
throw new Error('Async param matchers are not supported');
}
if (result.issues) {
return { success: false };
}
const parsed = result.value;
if (
typeof parsed !== 'string' &&
typeof parsed !== 'number' &&
typeof parsed !== 'boolean' &&
typeof parsed !== 'bigint'
) {
throw new Error('Param matcher must return a string, number, boolean, or bigint');
}
return { success: true, value: parsed };View on GitHub (pinned to 03f1687fe6)
Solutions
- Rewrite the matcher's `validate` so it returns the result synchronously (no `async`, no awaited refinements)
- Move any async work (e.g. DB lookups) out of the matcher into the route's load function and validate there
- Use a sync-only schema API for the matcher (e.g. Valibot sync parsers, Zod `.safeParse` instead of async paths)
Example fix
// before
const matcher = defineMatcher({
'~standard': {
async validate(value) {
return (await existsInDb(value)) ? { value } : { issues: [{ message: 'nope' }] };
}
}
});
// after
const matcher = defineMatcher({
'~standard': {
validate(value) {
return /^[a-z0-9-]+$/.test(value) ? { value } : { issues: [{ message: 'invalid' }] };
}
}
}); Defensive patterns
Strategy: try-catch
Validate before calling
const result = matcher['~standard'].validate('test-value');
if (result instanceof Promise) {
throw new Error('Matcher must be synchronous');
} Type guard
function isSyncMatcher(matcher) {
const r = matcher['~standard'].validate('probe');
return !(r instanceof Promise);
} Try / catch
try {
const outcome = runMatcher(matcher, value);
} catch (e) {
if (e.message === 'Async param matchers are not supported') {
// replace matcher with a synchronous schema
}
throw e;
} Prevention
- Never mark matcher validate() as async
- Avoid async refinements/transforms from schema libraries in matchers
- Probe matchers with a sync validation check in tests
When it happens
Trigger: A matcher defined with `defineParams` uses an async Standard Schema implementation, or `run_matcher` is called with a matcher whose `validate(value)` returns a Promise instead of a plain result object.
Common situations: Writing a custom Standard Schema adapter with an `async validate()` method; using a schema library configured in async mode (e.g. async refinements/transforms in Valibot/Zod async APIs) for param matchers; upgrading a schema library so a previously sync validator became async.
Related errors
- Param matcher must return a string, number, boolean, or bigi
- Invalid param definition
- ${manifest_data.params} does not export `params` from `defin
- Missing params for dynamic route ID ${id}
- new ValidationError(result.issues) — carries the Standard Sc
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/64446323f1a16ee6.
Report an issue: GitHub.