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

  1. Set the base option to the parent directory and use a non-'../' pattern: glob({ base: '../shared', pattern: '*.md' }).
  2. Use an absolute file URL for base pointing at the parent directory.
  3. 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

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


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/90688a4ebdc31a8e. Report an issue: GitHub.