withastro/astro · error · Error
Glob patterns cannot start with `../`. Set the `base` option
Error message
Glob patterns cannot start with `../`. Set the `base` option to a parent directory instead.
What it means
Thrown as a plain Error (no AstroError code) by the glob() loader constructor when any pattern starts with '../'. Parent-directory traversal via the pattern is disallowed for security and predictability; the documented escape hatch is to relocate the base directory itself.
Source
Thrown at packages/astro/src/content/loaders/glob.ts:86
}
function checkPrefix(pattern: string | Array<string>, prefix: string) {
if (Array.isArray(pattern)) {
return pattern.some((p) => p.startsWith(prefix));
}
return pattern.startsWith(prefix);
}
export const secretLegacyFlag = Symbol('astro.legacy-glob');
/**
* Loads multiple entries, using a glob pattern to match files.
* @param pattern A glob pattern to match files, relative to the content directory.
*/
export function glob(globOptions: GlobOptions & { [secretLegacyFlag]?: boolean }): Loader {
if (checkPrefix(globOptions.pattern, '../')) {
throw new Error(
'Glob patterns cannot start with `../`. Set the `base` option to a parent directory instead.',
);
}
if (checkPrefix(globOptions.pattern, '/')) {
throw new Error(
'Glob patterns cannot start with `/`. Set the `base` option to a parent directory or use a relative path instead.',
);
}
const isLegacy = !!globOptions[secretLegacyFlag];
const userGenerateId =
globOptions?.generateId ?? ((opts: GenerateIdOptions) => generateIdDefault(opts, isLegacy));
// Coerce to string so numeric ids from YAML don't cause Set strict-equality mismatches
// against string store keys in the untouched-entries cleanup. See #17624.
const generateId = (opts: GenerateIdOptions) => String(userGenerateId(opts));
const fileToIdMap = new Map<string, string>();
View on GitHub (pinned to d081033d5f)
Solutions
- Set the base option to the parent directory and use a non-'../' pattern: glob({ base: '../shared', pattern: '*.md' }).
- Use an absolute file URL for base pointing at the parent directory.
- If the content lives outside the project, consider symlinking it into the project tree or copying it.
Example fix
// before
glob({ pattern: '../shared/posts/*.md' })
// after
glob({ base: '../shared', pattern: 'posts/*.md' }) Defensive patterns
Strategy: validation
Validate before calling
function normalizeGlobPattern(pattern: string | string[], base?: string) {
const arr = Array.isArray(pattern) ? pattern : [pattern];
for (const p of arr) {
if (p.startsWith('../')) throw new Error('Use base option instead of ../ in pattern');
}
} Type guard
const startsParentRelative = (p: string) => p.startsWith('../'); Prevention
- Prefer the base option over '../' in patterns.
- Keep content inside the project tree; symlink external content if needed.
- Write a small wrapper that rejects '../' patterns in your own config.
When it happens
Trigger: Calling glob({ pattern: '../shared/*.md' }) or glob({ pattern: ['../posts/*.md', 'local/*.md'] }) — any element of the pattern array beginning with '../'.
Common situations: Trying to pull in content from a sibling/parent directory (monorepo shared content, workspace packages); porting an existing glob from another tool that allowed '..'.
Related errors
- Glob patterns cannot start with `/`. Set the `base` option t
- File path must be relative to the site root. Got: ${filePath
- Live content collections must be defined in "src/live.config
- Collection loader for ${name} does not have a load method
- ContentLoaderReturnsInvalidId
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/90688a4ebdc31a8e.
Report an issue: GitHub.