tinyhumansai/openhuman · error · Error

Could not reach

Error message

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

What it means

Quick-add provider flow in AIPanel: after upserting the cloud provider and persisting its key, the panel probes the provider's /models endpoint; if the probe fails it first rolls back (re-flushes the prior provider wire list and clears the stored key with clearCloudProviderKey so no key is orphaned on disk, #5339) and then throws 'Could not reach <label>: <msg>' with the probe's own message appended. Unlike the dialog path (error 170) there is no skip-verification escape hatch here.

Solutions

  1. Verify the exact endpoint with curl - e.g. curl -H 'Authorization: Bearer <key>' <endpoint>/models - and fix URL or key accordingly
  2. Re-enter and re-save the provider: rollback already removed it and cleared the key, so the previous state is restored
  3. Check the console.warn '[ai-settings] provider /models probe failed' entry for the underlying msg
  4. For local runtimes confirm the server is actually listening on that port before saving
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the same request the panel will probe
async function providerReachable(endpoint: string, key: string): Promise<boolean> {
  try {
    const res = await fetch(`${endpoint.replace(/\/$/, '')}/models`, {
    headers: { Authorization: `Bearer ${key}` },
  });
    return res.ok;
  } catch {
    return false;
  }
}

Try / catch

// the throw happens after rollback - catch it, then let the user re-enter config
catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (msg.startsWith('Could not reach')) {
    // provider + key were rolled back; reopen the form pre-filled for correction
    setProviderSaveNotice({ slug, kind: 'probe-failed', message: msg });
  }
}

Prevention

When it happens

Trigger: Saving a provider whose /models probe rejects: wrong endpoint URL, invalid or expired API key, DNS/firewall block, provider reachable only behind a VPN, or a self-signed certificate failing TLS validation.

Common situations: Typo'd base URL (missing /v1, wrong region subdomain); key pasted with a trailing newline or from the wrong service; local gateways (Ollama/LM Studio) not running at save time; corporate proxies intercepting the probe.

Related errors


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

Appendix: 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 7491200858)