stablyai/orca · error · Error

invalid_orca_profile_project_transfer

Error message

invalid_orca_profile_project_transfer

What it means

Thrown by transferProjectArgsFromUnknown() (line 72) when the payload for orcaProfiles:transferProject is not an object at all. This is the shape branch; the content-validation branch is line 80. It runs before the active-target / source-active checks and before any filesystem transfer, so a malformed envelope never reaches transferOrcaProfileProject.

Source

Thrown at src/main/ipc/orca-profiles.ts:72

function profileIdFromArgs(args: unknown): string {
  if (
    !args ||
    typeof args !== 'object' ||
    typeof (args as SwitchOrcaProfileArgs).profileId !== 'string'
  ) {
    throw new Error('invalid_orca_profile_id')
  }
  const profileId = (args as SwitchOrcaProfileArgs).profileId.trim()
  if (!profileId) {
    throw new Error('invalid_orca_profile_id')
  }
  return profileId
}

function transferProjectArgsFromUnknown(args: unknown): TransferOrcaProfileProjectArgs {
  if (!args || typeof args !== 'object') {
    throw new Error('invalid_orca_profile_project_transfer')
  }
  const candidate = args as TransferOrcaProfileProjectArgs
  const sourceProfileId = candidate.sourceProfileId?.trim()
  const targetProfileId = candidate.targetProfileId?.trim()
  const repoId = candidate.repoId?.trim()
  const mode = candidate.mode
  if (!sourceProfileId || !targetProfileId || !repoId || (mode !== 'move' && mode !== 'copy')) {
    throw new Error('invalid_orca_profile_project_transfer')
  }
  return {
    sourceProfileId,
    targetProfileId,
    repoId,
    mode
  }
}

function findProjectsByPathArgsFromUnknown(args: unknown): FindOrcaProfileProjectsByPathArgs {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Pass the args object directly as the second IPC argument: { sourceProfileId, targetProfileId, repoId, mode }.
  2. Construct the payload at the call site from validated profile and repo ids, not from a possibly-undefined outer wrapper.
  3. If the source/target profile pickers are not both populated, disable the transfer button.
  4. Do not wrap the envelope — main reads the args object at the top level.

Example fix

// before
await ipcRenderer.invoke('orcaProfiles:transferProject', { payload: transferForm })

// after
await ipcRenderer.invoke('orcaProfiles:transferProject', {
  sourceProfileId: transferForm.sourceProfileId,
  targetProfileId: transferForm.targetProfileId,
  repoId: transferForm.repoId,
  mode: transferForm.mode
})
Defensive patterns

Strategy: validation

Validate before calling

function isTransferEnvelope(v: unknown): v is object {
  return typeof v === 'object' && v !== null && !Array.isArray(v)
}

if (!isTransferEnvelope(payload)) {
  setTransferError('Missing transfer details.')
  return
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v)
}

Try / catch

try {
  await ipcRenderer.invoke('orcaProfiles:transferProject', payload)
} catch (e) {
  if (e instanceof Error && e.message === 'invalid_orca_profile_project_transfer') {
    setTransferError('Provide source, target, repo, and mode.')
  } else throw e
}

Prevention

When it happens

Trigger: Invoking orcaProfiles:transferProject with undefined, null, a primitive, or an array as the sole argument.

Common situations: The renderer dispatched the transfer action with no payload (e.g. a button onClick with no args bound), or a refactor wrapped the args inside another object so the outer value is { payload: {...} } rather than the args themselves.

Related errors


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