vercel/turborepo · error · Error
Invalid ${description}: path must be an absolute, non-empty
Error message
Invalid ${description}: path must be an absolute, non-empty string without NUL or newline characters and cannot start with "-" What it means
assertSafeGitArgument() hardens downloadAndExtractExample() against git argument injection: the resolved project root and the temp directory must be non-empty absolute strings containing no NUL or newline bytes and must not start with '-'. Any violation throws before a git command runs.
Source
Thrown at packages/turbo-utils/src/examples.ts:493
/**
* Validates that a path is safe to use as a git CLI argument.
* Prevents argument injection by rejecting paths that:
* - Are empty or not a string
* - Contain NUL bytes (could truncate the argument)
* - Start with "-" (could be interpreted as a git option)
* - Are not absolute filesystem paths (helps ensure they cannot be mistaken
* for URLs or additional git options like "--upload-pack")
*/
function assertSafeGitArgument(value: string, description: string): void {
if (
!value ||
typeof value !== "string" ||
value.includes("\0") ||
value.includes("\n") ||
value.startsWith("-") ||
!isAbsolute(value)
) {
throw new Error(
`Invalid ${description}: path must be an absolute, non-empty string without NUL or newline characters and cannot start with "-"`
);
}
}
function formatError(error: unknown): string {
if (error && typeof error === "object" && "stderr" in error) {
const { stderr } = error as { stderr?: unknown };
if (typeof stderr === "string" || Buffer.isBuffer(stderr)) {
const output = stderr.toString().trim();
if (output) {
return output;
}
}
}
return error instanceof Error ? error.message : String(error);
}View on GitHub (pinned to 9f94a7d215)
Solutions
- Sanitize the root before calling: strip control characters (root.replace(/[\0\n\r]/g, '')) and trim whitespace
- Pass an absolute path: path.resolve(cwd, input) before invoking downloadAndExtractExample
- Fix the upstream script or CI variable that injects the whitespace into the path
Example fix
// before
await downloadAndExtractExample(`${root}\n`, name); // newline from untrimmed input
// after
const safeRoot = path.resolve(root.replace(/[\0\n\r]/g, '').trim());
await downloadAndExtractExample(safeRoot, name); Defensive patterns
Strategy: validation
Validate before calling
import { isAbsolute, resolve } from "node:path";
function toSafeRoot(input: string): string {
const cleaned = input.replace(/[\0\n\r]/g, "").trim();
const abs = resolve(cleaned);
if (!isAbsolute(abs) || abs.startsWith("-")) throw new Error(`Unsafe root: ${JSON.stringify(input)}`);
return abs;
} Type guard
function isSafeGitPath(value: string): boolean {
return Boolean(value) && !value.includes("\0") && !value.includes("\n") && !value.startsWith("-") && isAbsolute(value);
} Try / catch
try {
await downloadAndExtractExample(root, name);
} catch (e) {
if (e instanceof Error && e.message.includes("path must be an absolute, non-empty string")) {
// your input path contains control characters or is relative — sanitize and retry
} else throw e;
} Prevention
- Always pass path.resolve()'d absolute paths to download APIs
- Trim and strip control characters from paths sourced from env vars or command substitution
- Fail fast in CI on paths containing newlines (common unquoted-variable bug)
When it happens
Trigger: Passing a root path that contains a newline or NUL byte (unquoted CI variables, untrimmed command substitution output, control characters pasted into scripts), or a root that does not resolve to an absolute path on the platform.
Common situations: CI matrix jobs interpolating unsanitized path variables; shell scripts building paths from $(cat file) without trimming; paths copied with trailing whitespace or embedded line breaks.
Related errors
- Directory path contains potentially unsafe characters: ${dir
- `git ${args[0]}` failed: ${formatError(error)}
- Invalid example name: ${name}
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/398806495de86eb2.
Report an issue: GitHub.