tinyhumansai/openhuman · error
[transport:cloud] HTTP
Error message
[transport:cloud] HTTP ${response.status}: ${text || response.statusText} What it means
The cloud transport's POST to the configured rpcUrl returned a non-2xx status; the response body text (or statusText when empty) is inlined with the status code. Unlike the local coreRpcClient, this path does NO error classification — no auth_expired detection, no session event — it is a plain Error, so 401s from the cloud core will not auto-sign the user out.
Solutions
- Read the status from the message prefix: 401/403 → refresh the profile's bearer token; 404 → fix the rpcUrl to include the RPC path; 5xx → provider-side, retry with backoff
- Use testCoreRpcConnection(url, token) to validate a freshly entered URL/token before saving the profile
- Re-save the connection profile after cloud re-authentication so the token is current
Example fix
// before
const resp = await transport.call('core.ping', {});
// after
const probe = await testCoreRpcConnection(url, candidateToken);
if (!probe.ok) throw new Error(`profile invalid: HTTP ${probe.status}`);
setActiveCoreTransport(new CloudHttpTransport(url, candidateToken)); Defensive patterns
Strategy: validation
Validate before calling
import { testCoreRpcConnection } from '../../coreRpcClient';
async function profileReachable(url: string, token?: string): Promise<boolean> {
try { return (await testCoreRpcConnection(url, token)).ok; } catch { return false; }
} Type guard
function isCloudHttpError(err: unknown): err is Error & { message: string } {
return err instanceof Error && /^\[transport:cloud\] HTTP \d{3}/.test(err.message);
}
function httpStatusOf(err: unknown): number | null {
const m = err instanceof Error ? err.message.match(/HTTP (\d{3})/) : null;
return m ? Number(m[1]) : null;
} Try / catch
try {
return await transport.call(method, params);
} catch (err) {
const status = httpStatusOf(err);
if (status === 401 || status === 403) { await refreshProfileToken(); return transport.call(method, params); }
if (status === 404) throw new ConfigError('cloud RPC URL missing /rpc path');
throw err;
} Prevention
- Validate URL+token with testCoreRpcConnection before installing the transport
- This path never auto-expires sessions — implement your own 401 handling for cloud profiles
- Re-save the connection profile after cloud re-auth
When it happens
Trigger: 401/403 from an expired or wrong bearerToken in the connection profile; 404 from a mis-typed cloud RPC URL; 502/503 from the cloud provider; TLS-terminating proxies rejecting the request.
Common situations: Connection profile saved with an old token after cloud re-auth; URL pointing at a REST base instead of the /rpc path; provider outage; firewall rewriting host headers.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- [transport:lan] HTTP
- [transport:manager] cloud profile missing rpcUrl
- Cloud RPC returned an error
- [transport:cloud] timed out after ms
- [transport:cloud] response missing result
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/32b07ce8902062f5.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/transport/CloudHttpTransport.ts:75
try {
response = await fetch(this.rpcUrl, {
method: 'POST',
headers,
body: JSON.stringify(payload),
signal: controller.signal,
});
} catch (err) {
if (controller.signal.aborted) {
throw new Error(`[transport:cloud] ${method} timed out after ${this.timeoutMs}ms`);
}
throw err;
} finally {
clearTimeout(timeoutId);
}
if (!response.ok) {
const text = await response.text();
throw new Error(`[transport:cloud] HTTP ${response.status}: ${text || response.statusText}`);
}
const json = (await response.json()) as JsonRpcResponse<T>;
if (json.error) {
logErr('[transport:cloud] ← %s error: %s', method, json.error.message);
throw new Error(json.error.message ?? 'Cloud RPC returned an error');
}
if (!Object.prototype.hasOwnProperty.call(json, 'result')) {
throw new Error('[transport:cloud] response missing result');
}
log('[transport:cloud] ← %s id=%d ok', method, id);
return json.result as T;
}
async *stream<T>(
method: string,View on GitHub (pinned to 7491200858)