stablyai/orca · error · Error

${label} is required

Error message

${label} is required

What it means

Thrown by validateRequiredString() inside the 'fs:downloadFolder' IPC handler when either args.dirPath or args.connectionId is not a non-empty string. The guard rejects undefined, non-string, and whitespace-only values before any SSH or filesystem work begins, so the message reports the offending field name (the ${label}). It is a contract violation between the renderer and the main-process handler, not a filesystem or network failure.

Source

Thrown at src/main/ipc/filesystem-download-folder.ts:15

import { BrowserWindow, dialog, ipcMain } from 'electron'
import { randomUUID } from 'node:crypto'
import { rm, stat } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { getRuntimePathBasename } from '../../shared/cross-platform-path'
import { sanitizeLocalDownloadFilename } from '../local-download-filename'
import { promoteLocalDownloadedFolder } from '../local-downloaded-folder-promotion'
import { requireSshFilesystemProvider } from '../providers/ssh-filesystem-dispatch'
import { isENOENT } from './filesystem-auth'

type DownloadFolderResult = { canceled: true } | { canceled: false; destinationPath: string }

function validateRequiredString(value: unknown, label: string): string {
  if (typeof value !== 'string' || value.trim() === '') {
    throw new Error(`${label} is required`)
  }
  return value
}

function createSiblingTransferPath(destinationPath: string, suffix: string): string {
  // Why: promotion uses rename/no-clobber operations that must stay on the
  // destination volume, so transfer paths intentionally remain siblings.
  return join(dirname(destinationPath), `.${randomUUID()}.${suffix}`)
}

async function assertDownloadFolderDestinationAvailable(destinationPath: string): Promise<void> {
  try {
    await stat(destinationPath)
  } catch (error) {
    if (isENOENT(error)) {
      return
    }
    throw error

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure the renderer only enables the Download action once both a concrete dirPath and an active connectionId are available, and pass them in the invoke payload.
  2. Guard in the renderer: skip the call when typeof dirPath !== 'string' or !connectionId.
  3. If this fires after a disconnect, re-establish the SSH connection so a fresh connectionId is set before retrying the download.

Example fix

// before
window.api.fs.downloadFolder({ dirPath: selectedNode?.path, connectionId })
// after
if (typeof selectedNode?.path === 'string' && selectedNode.path.trim() && connectionId) {
  await window.api.fs.downloadFolder({ dirPath: selectedNode.path, connectionId })
}
Defensive patterns

Strategy: validation

Validate before calling

// Renderer: validate both IPC args before invoking fs:downloadFolder
function canDownloadFolder(dirPath: unknown, connectionId: unknown): boolean {
  return typeof dirPath === 'string' && dirPath.trim().length > 0 &&
         typeof connectionId === 'string' && connectionId.trim().length > 0
}
if (!canDownloadFolder(selectedPath, connId)) { /* disable action */ }

Type guard

function isNonEmptyString(v: unknown): v is string {
  return typeof v === 'string' && v.trim().length > 0
}

Prevention

When it happens

Trigger: The renderer invokes ipcRenderer.invoke('fs:downloadFolder', { dirPath, connectionId }) with dirPath undefined/empty (e.g. the user triggered download on a non-resolved tree node) or with connectionId missing/cleared after the SSH target was disconnected and the connection id was reset to undefined.

Common situations: A UI code path that offers 'Download folder' before the selected node has a concrete remote path; a stale handler binding that still fires after disconnect cleared connectionId; a refactored renderer payload that renamed the fields; testing the IPC channel directly with partial args.

Related errors


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