vercel/turborepo · error · Error
Invalid example name: ${name}
Error message
Invalid example name: ${name} What it means
downloadAndExtractExample() validates the example name against /^[a-zA-Z0-9_-]+$/ before doing any work, explicitly to block path traversal (../) and git argument injection. Empty names, or names containing dots, slashes, spaces, or any character outside letters/digits/hyphen/underscore, are rejected.
Source
Thrown at packages/turbo-utils/src/examples.ts:540
try {
rmSync(tempDir, {
recursive: true,
force: true,
maxRetries: 5,
retryDelay: 100
});
} catch (error) {
warn(
`Unable to remove temporary directory ${tempDir}:\n${formatError(error)}`
);
}
}
export async function downloadAndExtractExample(root: string, name: string) {
// Validate example name to prevent path traversal and argument injection
// Only allow alphanumeric characters, hyphens, and underscores
if (!name || !/^[a-zA-Z0-9_-]+$/.test(name)) {
throw new Error(`Invalid example name: ${name}`);
}
// Normalize and validate the root directory to prevent unsafe git arguments
const normalizedRoot = resolve(root);
assertSafeGitArgument(normalizedRoot, "project root");
const tempDir = join(normalizedRoot, ".turbo-clone-temp");
assertSafeGitArgument(tempDir, "temporary directory");
try {
// Clone with partial clone (no blobs) and no checkout
runGit([
"clone",
"--filter=blob:none",
"--no-checkout",
"--depth",
"1",
"--sparse",View on GitHub (pinned to 9f94a7d215)
Solutions
- Pass the bare example directory name only: 'basic', 'with-vite', not a path
- Normalize input before calling: name.trim().split('/').pop()
- For arbitrary repos or nested paths, use downloadAndExtractRepo with a repo shorthand instead
Example fix
// before await downloadAndExtractExample(root, 'examples/basic'); // throws // after await downloadAndExtractExample(root, 'basic');
Defensive patterns
Strategy: validation
Validate before calling
const EXAMPLE_NAME = /^[a-zA-Z0-9_-]+$/;
function normalizeExampleName(input: string): string {
return input.trim().split("/").pop() ?? "";
}
const name = normalizeExampleName(userInput);
if (!EXAMPLE_NAME.test(name)) throw new Error(`Unsupported example name: ${userInput}`); Type guard
function isValidExampleName(name: string): boolean {
return /^[a-zA-Z0-9_-]+$/.test(name);
} Try / catch
try {
await downloadAndExtractExample(root, name);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Invalid example name:")) {
// re-prompt with a sanitized name or list valid examples
} else throw e;
} Prevention
- Accept bare directory names in CLIs; strip 'examples/' prefixes from user input
- Validate against the same [a-zA-Z0-9_-] charset in your own tooling
- Never pass free-form user input as the example name without the regex check
When it happens
Trigger: Calling downloadAndExtractExample(root, name) with values like 'examples/basic', '../basic', 'basic.', 'my example', '' — anything failing the strict charset regex. Note that dots are rejected, so even plausible-looking names with '.v2' suffixes fail.
Common situations: Users pasting a path from the docs (examples/with-tailwind) instead of the bare name; scripts interpolating unsanitized user input; trailing dots or spaces from copy-paste.
Related errors
- Unable to write .gitignore
- Unable to read package.json
- Unable to write package.json
- Unable to update README.md
- Directory path contains potentially unsafe characters: ${dir
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/86d8c4e25a3bbeb2.
Report an issue: GitHub.