jlcodes99/cockpit-tools · error

[AccountGroups] Failed to load groups: ${String(error)}

Error message

[AccountGroups] Failed to load groups: ${String(error)}

What it means

loadGroupsFromDisk wraps any failure from the Tauri 'load_account_groups' invoke or from parseGroups into a uniform '[AccountGroups] Failed to load groups: ...' error. Errors already prefixed with '[AccountGroups]' (e.g. from parseGroups) are re-thrown unchanged to avoid double wrapping. It signals that the persisted account-groups file could not be read or parsed.

Source

Thrown at src/services/accountGroupService.ts:96

      accountIds: [...group.accountIds],
      // Keep older files without createdAt readable without treating them as
      // an empty data set.
      createdAt: typeof group.createdAt === 'number' ? group.createdAt : 0,
    } as AccountGroup;
  });

  return cloneGroups(groups);
}

async function loadGroupsFromDisk(): Promise<AccountGroup[]> {
  try {
    const raw: string = await invoke('load_account_groups');
    return parseGroups(raw);
  } catch (error) {
    if (error instanceof Error && error.message.startsWith('[AccountGroups]')) {
      throw error;
    }
    throw new Error(`[AccountGroups] Failed to load groups: ${String(error)}`);
  }
}

async function saveGroupsToDisk(groups: AccountGroup[]): Promise<void> {
  try {
    await invoke('save_account_groups', { data: JSON.stringify(groups, null, 2) });
  } catch (e) {
    console.error('[AccountGroups] Failed to save to disk:', e);
    throw e;
  }
}

/** 迁移 localStorage 数据到磁盘(仅首次) */
async function migrateLegacyData(): Promise<void> {
  try {
    const raw = localStorage.getItem(LEGACY_STORAGE_KEY);
    if (!raw) return;
    const legacy = JSON.parse(raw);

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Inspect the wrapped cause in the message (the String(error) suffix) to identify whether the backend invoke or the parser failed
  2. Verify the Rust command 'load_account_groups' is registered and that the groups file path is writable/readable
  3. Delete or repair the corrupted account-groups file so the backend can recreate it
  4. Catch this error in the UI and fall back to an empty group list instead of crashing

Example fix

// before
const groups = await loadGroups();
// after
let groups;
try {
  groups = await loadGroups();
} catch (error) {
  console.warn('falling back to empty groups', error);
  groups = [];
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure backend capability before call
if (!('__TAURI__' in window)) throw new Error('backend unavailable');

Type guard

function isAccountGroupsError(e: unknown): e is Error {
  return e instanceof Error && e.message.startsWith('[AccountGroups]');
}

Try / catch

try {
  groups = await loadGroups();
} catch (e) {
  if (isAccountGroupsError(e)) {
    console.error('[AccountGroups]', e.message);
    groups = []; // or surface e.message to the user
  } else throw e;
}

Prevention

When it happens

Trigger: The Rust command 'load_account_groups' rejects (file missing, permission denied, backend error) or parseGroups throws a non-prefixed error during JSON parsing/validation of the raw string.

Common situations: First run with no groups file on disk, corrupted or hand-edited groups file, backend not compiled/registered for 'load_account_groups', or insufficient file-system permissions.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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