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
- Inspect the wrapped cause in the message (the String(error) suffix) to identify whether the backend invoke or the parser failed
- Verify the Rust command 'load_account_groups' is registered and that the groups file path is writable/readable
- Delete or repair the corrupted account-groups file so the backend can recreate it
- 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
- Include the underlying cause in the wrapped message and log it server-side
- Seed a valid default groups file on first run
- Add backend tests for load_account_groups with missing and corrupted files
- Catch and degrade gracefully in the UI instead of letting it bubble to a crash
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
- [WorkbuddyAutoCheckin] 读取后端签到日志失败:
- 加载诊断配置失败:
- errorCode (parseJsonOrThrow caller-supplied)
- Claude login start 响应缺少关键字段
- ${updatedAccount.quota_error.message}
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/9aea3c5721dcbc7f.
Report an issue: GitHub.