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

  1. Sanitize entries: strip leading slashes/backslashes and drive prefixes, and reject '..' segments before calling normalize.
  2. Always pass repo-relative paths; compute them via path.relative(repoRoot, absPath) when starting from absolute inputs.
  3. Run normalizeSparseDirectories in a try/catch and report the offending entry to the user.
  4. 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

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


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/c6a80360ca4e1695. Report an issue: GitHub.