stablyai/orca · error · Error
Sparse checkout directories must be repo-relative paths.
Error message
Sparse checkout directories must be repo-relative paths.
What it means
The canonical low-level error thrown by normalizeSparseDirectories in src/main/ipc/sparse-checkout-directories.ts. It fires when an entry is detected as absolute by isAbsoluteSparseDirectoryPath (leading '/', leading '\\', or a Windows drive-letter pattern /^[A-Za-z]:/), or when any segment after slash-split equals '..'. The wrapper in repos.ts (1291) re-words this for the preset UI, but direct callers of normalizeSparseDirectories see this message.
Source
Thrown at src/main/ipc/sparse-checkout-directories.ts:14
const WINDOWS_DRIVE_PATH_PATTERN = /^[A-Za-z]:/
function isAbsoluteSparseDirectoryPath(entry: string): boolean {
return entry.startsWith('/') || entry.startsWith('\\') || WINDOWS_DRIVE_PATH_PATTERN.test(entry)
}
export function normalizeSparseDirectories(directories: string[]): string[] {
const seen = new Set<string>()
return directories
.map((entry) => entry.trim())
.map((entry) => {
// Why: absolute paths can look repo-relative after slash normalization.
if (isAbsoluteSparseDirectoryPath(entry)) {
throw new Error('Sparse checkout directories must be repo-relative paths.')
}
return entry.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '')
})
.filter((entry) => entry.length > 0 && entry !== '.')
.filter((entry) => {
if (entry.split('/').includes('..')) {
throw new Error('Sparse checkout directories must be repo-relative paths.')
}
if (seen.has(entry)) {
return false
}
seen.add(entry)
return true
})
}
View on GitHub (pinned to 1136503c6a)
Solutions
- Sanitize entries: strip leading slashes/backslashes and drive prefixes, and reject '..' segments before calling normalize.
- Always pass repo-relative paths; compute them via path.relative(repoRoot, absPath) when starting from absolute inputs.
- Run normalizeSparseDirectories in a try/catch and report the offending entry to the user.
- In config ingestion, validate with the same helper and reject the config with a precise error.
Example fix
// before
const dirs = userInput // may contain 'C:\src' or '../x'
const normalized = normalizeSparseDirectories(dirs)
// after
import { relative } from 'path'
const dirs = userInput.map((p) =>
path.isAbsolute(p) ? relative(repoRoot, p) : p
).filter((p) => p && !p.startsWith('..'))
const normalized = normalizeSparseDirectories(dirs) Defensive patterns
Strategy: validation
Validate before calling
const DRIVE_RE = /^[A-Za-z]:/
function sanitizeSparseEntry(entry: string): string | null {
let t = entry.trim()
if (!t || t === '.') return null
if (t.startsWith('/') || t.startsWith('\\') || DRIVE_RE.test(t)) return null // absolute
t = t.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '')
if (t.split('/').includes('..')) return null // parent escape
return t || null
}
const clean = directories.map(sanitizeSparseEntry).filter((d): d is string => d !== null)
if (clean.length === 0) throw new Error('No valid repo-relative directories.')
const normalized = normalizeSparseDirectories(clean) Type guard
const DRIVE_RE = /^[A-Za-z]:/
function isRepoRelativeSparsePath(entry: string): boolean {
const t = entry.trim()
if (!t || t === '.') return false
if (t.startsWith('/') || t.startsWith('\\') || DRIVE_RE.test(t)) return false
if (t.replace(/\\/g, '/').split('/').includes('..')) return false
return true
} Try / catch
try {
normalized = normalizeSparseDirectories(directories)
} catch (e) {
if (/repo-relative/i.test((e as Error).message)) {
reportInvalidEntries(directories)
} else throw e
} Prevention
- Compute sparse paths with path.relative(repoRoot, absPath) when starting from absolute inputs.
- Reject absolute prefixes and '..' segments at the input boundary.
- Dry-run normalizeSparseDirectories and report the offending entry.
When it happens
Trigger: Calling normalizeSparseDirectories with entries like '/abs/path', '\\server\share', 'C:\dir', 'a/../b', or '../sibling'. Each is rejected because, after backslash-to-slash conversion and edge trimming, it would resolve outside the worktree root or be ambiguous.
Common situations: Code paths that accept user or config-provided sparse paths without sanitizing; cross-platform configs mixing Windows and POSIX paths; copy-paste of absolute paths from file explorers; tools that build sparse sets from filesystem walks.
Related errors
- Preset directories must be repo-relative paths.
- No Claude credentials found in ${resolvedDir}. Run `claude l
- --serve-project-root must be a directory: ${options.projectR
- Selected file is not a markdown document.
- Upload source changed while being inspected: ${sourcePath}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/c6a80360ca4e1695.
Report an issue: GitHub.