stablyai/orca · warning · Error

Preset directories must be repo-relative paths.

Error message

Preset directories must be repo-relative paths.

What it means

Thrown by normalizeSparsePresetDirectories when normalizeSparseDirectories throws its repo-relative error. This re-wraps the lower-level message ('Sparse checkout directories must be repo-relative paths.') into the preset-specific wording, then re-throws any other error unchanged. It means an entry was absolute (leading slash/backslash or a Windows drive letter) or contained a '..' parent segment.

Source

Thrown at src/main/ipc/repos.ts:2783

  if (!trimmed) {
    throw new Error('Preset name is required.')
  }
  if (trimmed.length > 80) {
    throw new Error('Preset name is too long.')
  }
  return trimmed
}

function normalizeSparsePresetDirectories(directories: string[]): string[] {
  let normalized: string[]
  try {
    normalized = normalizeSparseDirectories(directories)
  } catch (err) {
    if (
      err instanceof Error &&
      err.message === 'Sparse checkout directories must be repo-relative paths.'
    ) {
      throw new Error('Preset directories must be repo-relative paths.')
    }
    throw err
  }
  if (normalized.length === 0) {
    throw new Error('Preset must have at least one directory.')
  }
  return normalized
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Validate each directory with the same isAbsoluteSparseDirectoryPath / '..' rules in the renderer before save.
  2. Strip leading slashes, backslashes, and drive prefixes, and reject '..' segments in the input UI.
  3. Reuse the shared normalizeSparseDirectories on the renderer (it is pure) to preview normalization.
  4. Show inline per-entry validation feedback as the user edits the directory list.

Example fix

// before
ipc.invoke('sparsePresets:save', { repoId, name, directories })

// after
import { normalizeSparseDirectories } from '@main/ipc/sparse-checkout-directories'
try {
  normalizeSparseDirectories(directories) // dry-run on renderer
} catch (e) {
  setDirectoryError('Use repo-relative paths, no ".." or drive letters.')
  return
}
ipc.invoke('sparsePresets:save', { repoId, name, directories })
Defensive patterns

Strategy: validation

Validate before calling

import { normalizeSparseDirectories } from '@main/ipc/sparse-checkout-directories'

try {
  normalizeSparseDirectories(directories) // dry-run
} catch (e) {
  setDirectoryError('Use repo-relative paths; no leading slashes, drive letters, or "..".')
  return
}
await ipc.invoke('sparsePresets:save', { repoId, name, directories })

Type guard

const DRIVE_RE = /^[A-Za-z]:/
function isRepoRelativeDirectory(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 {
  await ipc.invoke('sparsePresets:save', { repoId, name, directories })
} catch (e) {
  if (/repo-relative/i.test((e as Error).message)) {
    setDirectoryError('One or more paths are not repo-relative.')
  } else throw e
}

Prevention

When it happens

Trigger: A user types 'C:\src' or '/home/user/repo' as a sparse directory; a path with a '..' segment like '../sibling'; a backslash-prefixed Windows path. normalizeSparseDirectories rejects these because they could escape the worktree after slash normalization.

Common situations: Users pasting full filesystem paths copied from an explorer; cross-platform input where Windows users type drive letters; templates that bundle absolute paths; path fields that were not validated client-side.

Related errors


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