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
- Choose a non-root destination directory with a clear parent (e.g. '/home/user/repos' not '//server/share').
- Verify the URL yields a clean repoName via deriveCloneRepoNameFromUrl before calling clone.
- Re-test with relativePathInsideRoot(destination, join(destination, repoName)) locally before invoking the clone IPC.
- 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
- Avoid cloning into a UNC root ('//server/share'); use a subdirectory as the parent.
- Run clonePathStaysInsideDestination locally before invoking clone for unusual URLs or Windows hosts.
- If the branch fires despite a clean URL, file a bug — deriveCloneRepoNameFromUrl and joinRemotePath are designed to make it unreachable.
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
- Clone destination must be an absolute path on the SSH host
- Windows inner executable does not exist: ${executablePath}
- Windows inner executable path is not a file: ${executablePat
- invalid_argument
- Managed Claude auth directory does not exist on disk.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/f3ab9c9906791740.
Report an issue: GitHub.