{"record":{"id":"74054df4e2ed3a56","repo":"farion1231/cc-switch","slug":"claude-desktop-official-provider-was-not-created","errorCode":null,"errorMessage":"Claude Desktop official provider was not created","messagePattern":"Claude Desktop official provider was not created","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/query/mutations.ts","lineNumber":52,"sourceCode":"        ensureCodexOfficialSeed?: boolean;\n        ensureGrokBuildOfficialSeed?: boolean;\n      },\n    ) => {\n      const {\n        providerKey: _providerKey,\n        addToLive,\n        ensureClaudeDesktopOfficialSeed,\n        ensureCodexOfficialSeed,\n        ensureGrokBuildOfficialSeed,\n        ...rest\n      } = providerInput;\n\n      if (appId === \"claude-desktop\" && ensureClaudeDesktopOfficialSeed) {\n        await providersApi.ensureClaudeDesktopOfficialProvider();\n        const providers = await providersApi.getAll(appId);\n        const officialProvider = providers[\"claude-desktop-official\"];\n        if (!officialProvider) {\n          throw new Error(\"Claude Desktop official provider was not created\");\n        }\n        return officialProvider;\n      }\n\n      if (appId === \"codex\" && ensureCodexOfficialSeed) {\n        // The fixed seed is the one native \"Codex current login\" card.\n        // A managed account gets its own provider row so several accounts can\n        // coexist without replacing that native-login entry.\n        const managedAccountId = resolveManagedAccountId(\n          rest.meta,\n          \"codex_oauth\",\n        )?.trim();\n        if (!managedAccountId) {\n          await providersApi.ensureCodexOfficialProvider();\n          const providers = await providersApi.getAll(appId);\n          const nativeLoginProvider = providers[CODEX_OFFICIAL_PROVIDER_ID];\n          if (!nativeLoginProvider) {\n            throw new Error(\"Codex current-login provider was not created\");","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/farion1231/cc-switch/blob/a2e22f330273a5b6ffa87cb8b82b624601bac562/src/lib/query/mutations.ts#L34-L70","documentation":"Thrown inside useAddProviderMutation's mutationFn when appId is 'claude-desktop' with ensureClaudeDesktopOfficialSeed set: after calling providersApi.ensureClaudeDesktopOfficialProvider(), the expected 'claude-desktop-official' entry is missing from providersApi.getAll('claude-desktop'). It signals that the backend seed routine returned without creating (or exposing) the official provider - an invariant break, not a user-input error.","triggerScenarios":"mutateAsync({ appId: 'claude-desktop', providerInput: { ensureClaudeDesktopOfficialSeed: true, ... } }) where the ensure command silently no-ops, the getAll read races the write, or the returned map lacks the 'claude-desktop-official' key.","commonSituations":"First run on a fresh data dir where seeding failed; frontend/backend version mismatch after the provider id changed; read-after-write race right after installation.","solutions":["Check the ensureClaudeDesktopOfficialProvider backend command for a silent early return (missing config file, logged-and-swallowed error)","Retry the mutation once - transient read-after-write races often clear","Manually verify getAll('claude-desktop') includes the 'claude-desktop-official' key after a manual ensure call"],"exampleFix":"// before\nawait providersApi.ensureClaudeDesktopOfficialProvider();\nconst official = (await providersApi.getAll(appId))[\"claude-desktop-official\"];\nif (!official) throw new Error(\"Claude Desktop official provider was not created\");\n\n// after\nawait providersApi.ensureClaudeDesktopOfficialProvider();\nlet official: Provider | undefined;\nfor (let i = 0; i < 3 && !official; i++) {\n  await new Promise((r) => setTimeout(r, 100 * (i + 1)));\n  official = (await providersApi.getAll(appId))[\"claude-desktop-official\"];\n}\nif (!official) throw new Error(\"Claude Desktop official provider was not created\");","handlingStrategy":"retry","validationCode":"// Skip the ensure path entirely when the provider already exists\nconst existing = (await providersApi.getAll(\"claude-desktop\"))[\"claude-desktop-official\"];\nif (existing) {\n  return existing; // no ensure call, no race window\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await addProvider.mutateAsync(input);\n} catch (e) {\n  if (e instanceof Error && e.message === \"Claude Desktop official provider was not created\") {\n    await queryClient.invalidateQueries({ queryKey: providersKeys.all });\n    return await addProvider.mutateAsync(input); // one retry after cache refresh\n  }\n  throw e;\n}","preventionTips":["Check whether the official provider already exists before triggering the ensure path","Log Object.keys(getAll()) output when the invariant fails","Keep the frontend provider id in sync with the backend seed constant"],"tags":["provider","seed","backend","claude-desktop","invariant"],"backgroundTag":null,"analyzedSha":"a2e22f330273a5b6ffa87cb8b82b624601bac562","analyzedAt":"2026-08-16T03:46:07.889Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}