stablyai/orca · error · Error

Clone path must be inside the destination directory

Error message

Clone path must be inside the destination directory

What it means

Thrown when relativePathInsideRoot(trimmedDestination, clonePath) === null. clonePath is built by joinRemotePath(host, trimmedDestination, repoName) where repoName comes from deriveCloneRepoNameFromUrl. The guard ensures the resulting clone path stays inside the chosen parent. deriveCloneRepoNameFromUrl already rejects '.', '..', and any name containing '/' or '\\', so a null result here typically indicates a Windows/UNC or path-traversal edge the join produced an out-of-tree result for.

Source

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

  if (!gitProvider) {
    throw new Error(`SSH connection "${args.connectionId}" not found or not connected`)
  }
  const fsProvider = getSshFilesystemProvider(args.connectionId)
  if (!fsProvider) {
    throw new Error(`SSH connection "${args.connectionId}" not found or not connected`)
  }
  const host = gitProvider.getHostPlatform?.()
  if (!host) {
    throw new Error('SSH host platform is unavailable. Reconnect the SSH target before cloning.')
  }
  const trimmedDestination = await resolveRemoteHomePath(args.connectionId, args.destination.trim())
  if (!isRuntimePathAbsolute(trimmedDestination, host.pathFlavor)) {
    throw new Error('Clone destination must be an absolute path on the SSH host')
  }
  const repoName = deriveCloneRepoNameFromUrl(args.url.trim())
  const clonePath = joinRemotePath(host, trimmedDestination, repoName)
  if (relativePathInsideRoot(trimmedDestination, clonePath) === null) {
    throw new Error('Clone path must be inside the destination directory')
  }
  const clonePathKey = normalizeRuntimePathForComparison(clonePath)
  const existing = store.getRepos().find((repo) => {
    return (
      repo.connectionId === args.connectionId &&
      normalizeRuntimePathForComparison(repo.path) === clonePathKey
    )
  })
  if (existing && !isFolderRepo(existing)) {
    emitRepoAdded('clone_url', true)
    return existing
  }

  const remoteCloneKey = `${args.connectionId}:${clonePathKey}`
  if (remoteCloneInFlightByPath.has(remoteCloneKey)) {
    throw new Error('A clone is already in progress for this SSH destination')
  }
  const controller = new AbortController()

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Choose a non-root destination directory with a clear parent (e.g. '/home/user/repos' not '//server/share').
  2. Verify the URL yields a clean repoName via deriveCloneRepoNameFromUrl before calling clone.
  3. Re-test with relativePathInsideRoot(destination, join(destination, repoName)) locally before invoking the clone IPC.
  4. If reproducible, file a bug — deriveCloneRepoNameFromUrl and joinRemotePath are designed to make this branch unreachable.
Defensive patterns

Strategy: validation

Validate before calling

import { relativePathInsideRoot } from '../../shared/cross-platform-path'
import { joinRemotePath } from '../ssh/ssh-remote-platform'
import { deriveCloneRepoNameFromUrl } from '../git/repo-clone-path'
import type { RemoteHostPlatform } from '../ssh/ssh-remote-platform'

function clonePathStaysInsideDestination(
  url: string,
  destination: string,
  host: RemoteHostPlatform
): boolean {
  const repoName = deriveCloneRepoNameFromUrl(url.trim())
  const clonePath = joinRemotePath(host, destination, repoName)
  return relativePathInsideRoot(destination, clonePath) !== null
}

Type guard

function isClonePathOutsideDestination(err: unknown): boolean {
  return err instanceof Error && err.message === 'Clone path must be inside the destination directory'
}

Try / catch

if (!clonePathStaysInsideDestination(url, trimmedDestination, host)) {
  surfaceUserAction('Choose a non-root destination directory (avoid UNC roots or paths that re-normalize outside the parent).')
  return
}
await cloneRemoteRepo(store, mainWindow, { connectionId, url, destination })

Prevention

When it happens

Trigger: joinRemotePath produced a clonePath that is not strictly beneath trimmedDestination. Possible with UNC root quirks ('//server/share' as destination where the joined result escapes via normalization), a destination that itself normalizes to a parent of the join, or a repoName that — while not '.' or '..' — interacts with windows drive handling to escape.

Common situations: Cloning into a UNC root ('//server/share') where the joined path re-normalizes outside the parent; windows path flavor with a destination that has a trailing separator that joinRemotePath collapses oddly; exotic repo names from URLs that survive deriveCloneRepoNameFromUrl's guards but still misbehave under join.

Related errors


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