{"record":{"id":"a7817337c1880a3d","repo":"tinyhumansai/openhuman","slug":"could-not-reach-upserted-label-msg","errorCode":null,"errorMessage":"Could not reach ${upserted.label}: ${msg}","messagePattern":"Could not reach (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/components/settings/panels/AIPanel.tsx","lineNumber":3105,"sourceCode":"                  message: describeProviderVerificationFailure(slug, msg, t),\n                });\n              } else {\n                // Auth failure (wrong key), or a local runtime that isn't up:\n                // roll both stores back and reject so the user fixes it. Rollback\n                // failures are LOGGED, never swallowed — a silently failed\n                // key-clear is exactly what orphans a key on disk (#5339).\n                await flushCloudProviders(priorWireProviders).catch(rollbackErr =>\n                  console.warn(`[ai-settings] rollback flush failed slug=${slug}`, rollbackErr)\n                );\n                if (isKeyProvider) {\n                  await clearCloudProviderKey(slug).catch(rollbackErr =>\n                    console.warn(\n                      `[ai-settings] rollback clearCloudProviderKey failed slug=${slug}`,\n                      rollbackErr\n                    )\n                  );\n                }\n                throw new Error(`Could not reach ${upserted.label}: ${msg}`);\n              }\n            }\n          }\n        }\n\n        const nextDraft = {\n          ...draft,\n          cloudProviders: [...draft.cloudProviders.filter(p => p.slug !== slug), upserted],\n        };\n        await persist(nextDraft);\n        if (isCodexOAuth && slug === 'openai') {\n          await clearCloudProviderKey(slug);\n        }\n        if (slug === 'openai') {\n          setCodexAuthError(null);\n        }\n        setKeyDialogFor(null);\n        setPendingLocalLabel(null);","sourceCodeStart":3087,"sourceCodeEnd":3123,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/components/settings/panels/AIPanel.tsx#L3087-L3123","documentation":"When saving a provider whose runtime requires a /models probe, a failed probe first triggers rollback (re-flush the previous provider wire list and clear the just-written key so nothing is orphaned on disk, cf. #5339) and then throws this error embedding the probe's own failure message.","triggerScenarios":"Endpoint unreachable (wrong URL/port), API key rejected (401/403), TLS/proxy failure, or a server returning non-OpenAI JSON — all during the save-time /models fetch.","commonSituations":"Typo'd base URL; key without quota or permission; self-signed certificate behind a corporate proxy; endpoint that is not actually OpenAI-compatible.","solutions":["Fix the underlying probe error shown after the colon (auth → new key; network → correct URL/proxy)","Confirm the endpoint is an OpenAI-compatible base that serves GET /models","Save again only after the endpoint verifiably works — the failed attempt already rolled back, so no orphaned key remains"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight the probe with the entered values before saving:\nconst ok = await fetch(`${endpoint}/models`, {\n  headers: { Authorization: `Bearer ${apiKey}` },\n}).then(r => r.ok);\nif (!ok) { /* block save; show reason */ }","typeGuard":"const isProbeFailure = (msg: string): boolean => msg.startsWith('Could not reach');","tryCatchPattern":"try {\n  await saveProvider(cfg);\n} catch (e) {\n  if (e instanceof Error && isProbeFailure(e.message)) {\n    // rollback already ran: fix key/URL from the embedded probe message and retry\n    return;\n  }\n  throw e;\n}","preventionTips":["curl the provider's /models with the key before saving","Confirm the endpoint is an OpenAI-compatible base URL","Trust the rollback: after this error no partial provider/key is left behind — just fix and re-save"],"tags":["ai-provider","network","api-key","settings","rollback"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}