mastra-ai/mastra · error
Missing required query param
Error message
Missing required query param: ${label} What it means
The filesystem route validates query params through `assertRelativePath`, which throws `Missing required query param: ${label}` when the parameter is absent or empty/whitespace after trimming. The label is the parameter name the caller must supply (e.g. 'path', 'root', 'previousPath'), so the message tells you exactly which query parameter is missing.
Solutions
- Append the required query parameter, e.g. `GET /api/fs/read?path=src/index.ts`.
- Check the error's label text and make sure the client sends a param with exactly that name.
- Ensure empty-string values are either rejected client-side or defaulted to '.'/workspace root before the request.
- Verify middleware/proxies are not stripping the query string.
Example fix
// before
await fetch(`/api/fs/read`); // missing ?path
// after
await fetch(`/api/fs/read?path=${encodeURIComponent(relativePath)}`); Defensive patterns
Strategy: validation
Validate before calling
function buildFsUrl(route: string, label: string, value: string | undefined): string {
if (!value || !value.trim()) throw new Error(`${label} is required before calling ${route}`);
return `${route}?${label}=${encodeURIComponent(value)}`;
} Try / catch
try {
return await api.fsRead({ path });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Missing required query param')) {
console.error('Client bug: a required fs query param was empty/absent.', err.message);
}
throw err;
} Prevention
- Reject empty path inputs at the UI/form layer before issuing requests.
- Always send query params explicitly with encodeURIComponent; never build URLs by string concatenation with optional segments.
- Check wrapper/fetch libraries for 'drop empty params' behavior.
When it happens
Trigger: Calling a /fs route (via safeRoot, safeRelativePath, safePath, or safePreviousPath handlers) without the required query string parameter, e.g. `GET /api/fs/read` with no `?path=`, or `?path=` / `?path=%20%20` (empty or whitespace-only).
Common situations: Frontend code building the URL conditionally and dropping the param when the value is an empty string; form inputs left blank; fetch wrappers stripping empty params; missing URL encoding causing the param to be dropped by middleware.
Related errors
- must be relative
- Query parameter "status" must be "draft" or "published"
- Agent ID is required
- File path does not exist
- [FilesystemStorage] duplicate file path
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/2a5624525d3e2cee.
Report an issue: GitHub.
Appendix: source
Thrown at mastracode/factory/src/routes/fs.ts:216
/**
* Resolve a path's real location (following symlinks) and confirm it stays
* within `root`. Returns the real path when confined, or `null` when it escapes
* the root or does not exist. Used so a symlink inside the root that points
* outside it cannot be browsed or selected.
*/
async function realPathWithinRoot(candidate: string, root: string): Promise<string | null> {
try {
const real = await realpath(candidate);
return isWithinRoot(real, root) ? real : null;
} catch {
return null;
}
}
function assertRelativePath(path: string, label: string): string {
const trimmed = path.trim();
if (!trimmed) throw new Error(`Missing required query param: ${label}`);
if (isAbsolute(trimmed)) throw new Error(`${label} must be relative`);
if (trimmed.split(/[\\/]+/).includes('..')) throw new Error(`${label} escapes workspace`);
const normalized = resolve('/', trimmed).slice(1);
if (!normalized || normalized === '..' || normalized.startsWith(`..${sep}`))
throw new Error(`${label} escapes workspace`);
return normalized;
}
function assertApprovedRenderedRoot(renderedRoot: string): string {
const safeRoot = assertRelativePath(renderedRoot, 'root');
if (!APPROVED_RENDERED_ROOTS.has(safeRoot)) throw new Error('Root is not approved for rendered workspace access');
return safeRoot;
}
async function confinedWorkspacePath(
root: string,
workspacePath: string,
): Promise<{ resolvedRoot: string; workspace: string }> {View on GitHub (pinned to 75dd419e61)