jlcodes99/cockpit-tools · error

transfer_selection_required

transfer_selection_required

Error message

transfer_selection_required

What it means

createManagedBackup requires a non-empty DataTransferSelection: without at least one platform/account/config selected, exportDataTransferJson would produce an empty or meaningless backup file. hasSelection(params.selection) failed, so the library aborts with transfer_selection_required instead of writing an empty backup.

Source

Thrown at src/services/scheduledBackupService.ts:353

}

export function isAutoBackupDue(settings: AutoBackupSettings, now = new Date()): boolean {
  if (!settings.enabled) return false;
  const selection = getSelectionFromAutoBackupSettings(settings);
  if (!hasSelection(selection)) return false;
  const lastBackupAt = normalizeDate(settings.last_backup_at);
  if (!lastBackupAt) return true;
  return now.getTime() - lastBackupAt.getTime() >= AUTO_BACKUP_INTERVAL_MS;
}

export async function createManagedBackup(params: {
  trigger: AutoBackupTrigger;
  selection: DataTransferSelection;
  retentionDays: number;
  markAsLastRun?: boolean;
}): Promise<ManagedBackupResult> {
  if (!hasSelection(params.selection)) {
    throw new Error('transfer_selection_required');
  }

  const executedAt = new Date();
  const content = await exportDataTransferJson(params.selection);
  const fileName = buildManagedBackupFileName(params.selection, params.trigger, executedAt);
  const path = await invoke<string>('write_auto_backup_file', {
    fileName,
    content,
  });
  const deletedFiles = await cleanupAutoBackupFilesInternal(params.retentionDays);

  if (params.markAsLastRun !== false) {
    await updateAutoBackupLastRunInternal(executedAt.toISOString());
  }

  dispatchAutoBackupStateChanged();

  return {

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Populate params.selection with at least one platform/account/config entry before calling createManagedBackup
  2. Run hasSelection-equivalent validation in the UI and disable the backup action until something is selected
  3. Re-initialize the persisted selection if an app update wiped it
  4. Gate the scheduler so auto-backup is skipped (not thrown) when selection is empty

Example fix

// before
await createManagedBackup({ trigger: 'manual', selection: emptySelection, retentionDays: 30 });
// after
if (!hasSelection(emptySelection)) {
  console.warn('Nothing selected for backup; skipping');
  return;
}
await createManagedBackup({ trigger: 'manual', selection: emptySelection, retentionDays: 30 });
Defensive patterns

Strategy: validation

Validate before calling

const hasSelection = (s: DataTransferSelection) =>
  Boolean(s.platforms?.length || s.accounts?.length || s.includeConfig);
if (!hasSelection(params.selection)) return; // skip instead of throwing

Type guard

function selectionIsNonEmpty(s: DataTransferSelection): boolean {
  return Object.values(s).some((v) => (Array.isArray(v) ? v.length > 0 : Boolean(v)));
}

Try / catch

try {
  await createManagedBackup(params);
} catch (e) {
  if (e.message === 'transfer_selection_required') {
    openSelectionSetupDialog();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createManagedBackup (directly or via the auto-backup scheduler) with a selection where all category flags are false / selected sets are empty — e.g. auto-backup fired when the user deselected everything, or code passed a default-initialized empty selection.

Common situations: Auto-backup trigger running before the user completed first-run selection setup, a persisted selection reset to empty after an app update, or a UI path allowing 'backup' with nothing checked.

Understand the failure class

Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/5ed10968cb5d53c4. Report an issue: GitHub.