tinyhumansai/openhuman · error

Could not reach ${upserted.label}: ${msg}

Error message

Could not reach ${upserted.label}: ${msg}

What it means

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.

Source

Thrown at app/src/components/settings/panels/AIPanel.tsx:3105

                  message: describeProviderVerificationFailure(slug, msg, t),
                });
              } else {
                // Auth failure (wrong key), or a local runtime that isn't up:
                // roll both stores back and reject so the user fixes it. Rollback
                // failures are LOGGED, never swallowed — a silently failed
                // key-clear is exactly what orphans a key on disk (#5339).
                await flushCloudProviders(priorWireProviders).catch(rollbackErr =>
                  console.warn(`[ai-settings] rollback flush failed slug=${slug}`, rollbackErr)
                );
                if (isKeyProvider) {
                  await clearCloudProviderKey(slug).catch(rollbackErr =>
                    console.warn(
                      `[ai-settings] rollback clearCloudProviderKey failed slug=${slug}`,
                      rollbackErr
                    )
                  );
                }
                throw new Error(`Could not reach ${upserted.label}: ${msg}`);
              }
            }
          }
        }

        const nextDraft = {
          ...draft,
          cloudProviders: [...draft.cloudProviders.filter(p => p.slug !== slug), upserted],
        };
        await persist(nextDraft);
        if (isCodexOAuth && slug === 'openai') {
          await clearCloudProviderKey(slug);
        }
        if (slug === 'openai') {
          setCodexAuthError(null);
        }
        setKeyDialogFor(null);
        setPendingLocalLabel(null);

View on GitHub (pinned to a221052e0d)

Solutions

  1. Fix the underlying probe error shown after the colon (auth → new key; network → correct URL/proxy)
  2. Confirm the endpoint is an OpenAI-compatible base that serves GET /models
  3. Save again only after the endpoint verifiably works — the failed attempt already rolled back, so no orphaned key remains
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the probe with the entered values before saving:
const ok = await fetch(`${endpoint}/models`, {
  headers: { Authorization: `Bearer ${apiKey}` },
}).then(r => r.ok);
if (!ok) { /* block save; show reason */ }

Type guard

const isProbeFailure = (msg: string): boolean => msg.startsWith('Could not reach');

Try / catch

try {
  await saveProvider(cfg);
} catch (e) {
  if (e instanceof Error && isProbeFailure(e.message)) {
    // rollback already ran: fix key/URL from the embedded probe message and retry
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Typo'd base URL; key without quota or permission; self-signed certificate behind a corporate proxy; endpoint that is not actually OpenAI-compatible.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/a7817337c1880a3d. Report an issue: GitHub.