Skip to content

fix: guard against undefined updatedAt when sorting provider accounts#1132

Open
dongsheng123132 wants to merge 1 commit into
ValueCell-ai:mainfrom
dongsheng123132:fix/provider-account-sort-undefined-updatedat
Open

fix: guard against undefined updatedAt when sorting provider accounts#1132
dongsheng123132 wants to merge 1 commit into
ValueCell-ai:mainfrom
dongsheng123132:fix/provider-account-sort-undefined-updatedat

Conversation

@dongsheng123132

Copy link
Copy Markdown

Problem

buildConfiguredModelOptions and buildRuntimeProviderOptions (in src/lib/model-options.ts), and the account-list builder in src/lib/provider-accounts.ts, sort accounts with:

return right.updatedAt.localeCompare(left.updatedAt);

This assumes every ProviderAccount.updatedAt is a string. But listProviderAccounts() returns the persisted providerAccounts map verbatim — no normalization / backfill:

export async function listProviderAccounts(): Promise<ProviderAccount[]> {
  const store = await getClawXProviderStore();
  const accounts = store.get('providerAccounts') as Record<string, ProviderAccount> | undefined;
  return Object.values(accounts ?? {});
}

So if a single persisted account is missing updatedAt (a record written by an external tool, an import/migration, or a hand-edited clawx-providers.json), updatedAt is undefined at runtime. As soon as there are ≥2 qualifying accounts, Array.sort invokes the comparator and the entire renderer crashes at the error boundary:

TypeError: Cannot read properties of undefined (reading 'localeCompare')
    at Array.sort (<anonymous>)
    at <useMemo>  // buildConfiguredModelOptions / buildRuntimeProviderOptions

This takes down both the Chat page (model picker) and the Agents page — the user only sees "Something went wrong", and the Reload button doesn't help because the malformed record is still on disk.

Fix

Make the three updatedAt comparators null-safe:

return (right.updatedAt ?? '').localeCompare(left.updatedAt ?? '');
  • src/lib/model-options.ts (×2 — buildRuntimeProviderOptions, buildConfiguredModelOptions)
  • src/lib/provider-accounts.ts (×1)

An empty string sorts such a record to the end (reasonable for an account with no known update time), and a single malformed record can no longer crash the whole app.

Repro

  1. Configure two provider accounts.
  2. In %APPDATA%/ClawX/clawx-providers.json, remove the updatedAt field from one entry under providerAccounts.
  3. Restart ClawX → "Something went wrong" / localeCompare crash.

With this patch, ClawX loads normally.

Note: a defense-in-depth follow-up would be to normalize/backfill createdAt/updatedAt in listProviderAccounts() (or providerConfigToAccount) so malformed persisted records are healed on read. This PR only fixes the crash itself, which is the minimal change.

🤖 Generated with Claude Code

The provider-account comparators call `updatedAt.localeCompare(...)`
assuming `updatedAt` is always a string. When a persisted account is
missing `updatedAt` (e.g. a record written by an external tool /
migration / a hand-edited clawx-providers.json), the value is
`undefined` and the whole renderer crashes at the error boundary:

    TypeError: Cannot read properties of undefined (reading 'localeCompare')
        at Array.sort (<anonymous>)
        at buildConfiguredModelOptions / buildRuntimeProviderOptions (useMemo)

`listProviderAccounts()` returns stored accounts verbatim without
normalization, so a single bad record takes down both the Chat page
(model picker) and the Agents page.

Make the three `updatedAt` comparators null-safe with `?? ''`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant