tinyhumansai/openhuman · error
[transport:lan] timed out after ms
Error message
[transport:lan] ${method} timed out after ${this.timeoutMs}ms What it means
LanHttpTransport.call aborts its fetch after this.timeoutMs (constructor arg, default 10_000 — a third of the cloud default) and reports it as this timeout error. As with the cloud transport, the caller's opts.signal is wired to the same AbortController, so caller-initiated cancellation is reported as a timeout too. LAN connections send no bearer header — they rely on network-level trust plus the session token in the profile — so this is purely a reachability/latency failure.
Solutions
- Raise the constructor timeoutMs for LAN profiles expected to run heavy RPCs (default 10s is tight)
- Verify the desktop is awake and the LAN address in the profile still resolves (mDNS/DHCP address changes)
- Distinguish caller cancellation from true timeout at the call site before reporting
- Retry idempotent reads once — transient Wi-Fi hiccups commonly trip the 10s budget
Example fix
// before const t = new LanHttpTransport(rpcUrl); // after const t = new LanHttpTransport(rpcUrl, 30_000); // budget for cold-start RPCs over Wi-Fi
Defensive patterns
Strategy: retry
Type guard
function isLanTransportTimeout(err: unknown): boolean {
return err instanceof Error && err.message.startsWith('[transport:lan]') && err.message.includes('timed out');
} Try / catch
const mySignal = new AbortController().signal;
try {
return await transport.call(method, params, { signal: mySignal });
} catch (err) {
if (isLanTransportTimeout(err) && !mySignal.aborted && isIdempotent(method)) {
return await transport.call(method, params);
}
if (mySignal.aborted) return cancelled();
throw err;
} Prevention
- The LAN default is only 10s — raise timeoutMs for heavy RPCs over Wi-Fi
- Verify the desktop is awake and its LAN address is current before long sessions
- Caller aborts are reported as timeouts here — always check your own signal first
When it happens
Trigger: Any callCoreRpc routed through an active lan-http transport (iOS/remote LAN profile) exceeding 10s: Wi-Fi latency, desktop core busy, phone waking from sleep mid-call; or a caller aborting its signal, mislabeled as timeout.
Common situations: Phone on a congested network against a desktop core; desktop asleep/locked so the loopback listener stalls; default 10s too tight for first-launch heavy RPCs over LAN; component unmount aborts polluting logs.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- [transport:cloud] timed out after ms
- Core RPC timed out after ms
- LAN RPC returned an error
- [transport:lan] HTTP
- [transport:lan] response missing result
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/9cd46846cdb8114e.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/transport/LanHttpTransport.ts:60
const payload: JsonRpcRequestBody = { jsonrpc: '2.0', id, method, params: params ?? {} };
log('[transport:lan] → %s id=%d', method, id);
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
opts?.signal?.addEventListener('abort', () => controller.abort());
let response: Response;
try {
response = await fetch(this.rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal: controller.signal,
});
} catch (err) {
if (controller.signal.aborted) {
throw new Error(`[transport:lan] ${method} timed out after ${this.timeoutMs}ms`);
}
throw err;
} finally {
clearTimeout(timeoutId);
}
if (!response.ok) {
const text = await response.text();
throw new Error(`[transport:lan] HTTP ${response.status}: ${text || response.statusText}`);
}
const json = (await response.json()) as JsonRpcResponse<T>;
if (json.error) {
logErr('[transport:lan] ← %s error: %s', method, json.error.message);
throw new Error(json.error.message ?? 'LAN RPC returned an error');
}
if (!Object.prototype.hasOwnProperty.call(json, 'result')) {View on GitHub (pinned to 7491200858)