tinyhumansai/openhuman · error
Core returned an empty backend URL
Error message
Core returned an empty backend URL
What it means
Thrown by the backend-URL resolver when the 'openhuman.config_resolve_api_url' RPC succeeds but both candidate fields (api_url / apiUrl) resolve to an empty or whitespace-only string after trim. Every cloud-backend call needs this URL, so the resolver fails loudly instead of letting callers build requests against ''.
Source
Thrown at app/src/services/backendUrl.ts:63
}
if (!coreIsTauri()) {
resolvedBackendUrl = webFallbackBackendUrl();
return resolvedBackendUrl;
}
if (resolvingBackendUrl) {
return resolvingBackendUrl;
}
const generation = backendUrlGeneration;
resolvingBackendUrl = (async () => {
const response = await callCoreRpc<{ api_url?: string; apiUrl?: string }>({
method: 'openhuman.config_resolve_api_url',
});
const resolved = String(response.api_url ?? response.apiUrl ?? '').trim();
if (!resolved) {
throw new Error('Core returned an empty backend URL');
}
const normalized = normalizeBaseUrl(resolved);
if (generation === backendUrlGeneration) {
resolvedBackendUrl = normalized;
}
return normalized;
})().finally(() => {
if (generation === backendUrlGeneration) {
resolvingBackendUrl = null;
}
});
return resolvingBackendUrl;
}
View on GitHub (pinned to a221052e0d)
Solutions
- Set the backend API URL: Settings in the app, or the backend URL key in the core config, or the documented env var in .env (see .env.example)
- Confirm the core finished config initialization before the resolver runs (restart the app if it raced first-launch init)
- Read back the raw value: call openhuman.config_resolve_api_url on /rpc and check the api_url field
- If running self-hosted without the cloud, avoid code paths that resolve the backend URL (they are cloud-only)
Example fix
# .env (before: missing) # .env (after) OPENHUMAN_BACKEND_API_URL=https://api.example.com
Defensive patterns
Strategy: try-catch
Validate before calling
// Check that a backend URL is configured before entering cloud-dependent flows
const hasBackend = await callCoreRpc<{ api_url?: string }>({ method: 'openhuman.config_resolve_api_url' })
.then(r => Boolean((r.api_url ?? '').trim()))
.catch(() => false);
if (!hasBackend) blockCloudFeatures('Set the backend API URL in Settings first.'); Type guard
function isResolvedBackendUrl(v: unknown): v is { api_url: string } {
const r = v as Record<string, unknown> | null | undefined;
return !!r && typeof r.api_url === 'string' && r.api_url.trim().length > 0;
} Try / catch
try {
const base = await resolveBackendUrl();
} catch (e) {
if (e instanceof Error && e.message.includes('empty backend URL')) {
promptUserToConfigureBackend(); // Settings / env — then retry resolution
} else throw e;
} Prevention
- Set the backend URL during onboarding before any cloud call can fire
- Keep the env override (.env / OPENHUMAN_BACKEND_API_URL) documented in .env.example
- Gate cloud-only features on a resolved URL so the error never surfaces mid-flow
When it happens
Trigger: Fresh workspace where config.toml has no backend/api URL set and no env override (e.g. OPENHUMAN_BACKEND_API_URL) is present; a config file with backend_api_url = "" ; the core's resolve handler answering with an empty string because neither config nor default was initialized yet.
Common situations: First run before onboarding sets the backend; self-hosted/custom-backend deployments that intentionally clear the cloud URL; core config migration wiping the value; testing against a core whose config was never initialized (config init not yet complete when resolve ran).
Related errors
- [transport:local] response missing result
- RPC token not provided and ${tokenPath} could not be read. P
- RPC ${method} returned non-JSON HTTP ${res.status}: ${bodyTe
- Invalid ${paramName}: '${value}'. Must be a valid integer ID
- Invalid ${paramName}: ${String(value)}. Type must be an inte
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/0a60992b3e4a92f5.
Report an issue: GitHub.