Motivation
Neither of the two fetch call sites sets a timeout, so any command that reaches a network
black hole (captive portal, dropped route, a data center that accepts the TCP connection but
never responds) hangs forever with the spinner spinning. The only escape is Ctrl-C.
Call sites
src/api.js:41 — the single transport path for every device/home/weather/notify/stats/ipc command:
const resp = await fetch(url, options);
src/commands/doctor.js:48 — ironically the "connectivity check" can itself hang:
const resp = await fetch(`${baseUrl}/v1.0/end-user/homes/all`, {
headers: { 'Authorization': `Bearer ${apiKey}` },
});
Suggestion
Node 18+ (the declared engines.node floor in package.json) ships AbortSignal.timeout(),
so this is a one-liner per call:
const resp = await fetch(url, { ...options, signal: AbortSignal.timeout(15000) });
A timed-out request rejects with a TimeoutError, which the existing catch blocks already
funnel into printError. The ipc polling helpers (ipcPicResolveWithWait,
ipcVideoResolveWithWait) intentionally take a long time, so a per-attempt timeout there is
fine and won't break the poll loop. Worth making the value configurable via an env var
(TUYA_HTTP_TIMEOUT_MS) for slow links.
This is orthogonal to the existing report about _request not checking resp.ok / resp.json()
— it's about the request that never completes at all rather than one that completes with a bad body.
Motivation
Neither of the two
fetchcall sites sets a timeout, so any command that reaches a networkblack hole (captive portal, dropped route, a data center that accepts the TCP connection but
never responds) hangs forever with the spinner spinning. The only escape is Ctrl-C.
Call sites
src/api.js:41— the single transport path for everydevice/home/weather/notify/stats/ipccommand:src/commands/doctor.js:48— ironically the "connectivity check" can itself hang:Suggestion
Node 18+ (the declared
engines.nodefloor inpackage.json) shipsAbortSignal.timeout(),so this is a one-liner per call:
A timed-out request rejects with a
TimeoutError, which the existingcatchblocks alreadyfunnel into
printError. Theipcpolling helpers (ipcPicResolveWithWait,ipcVideoResolveWithWait) intentionally take a long time, so a per-attempt timeout there isfine and won't break the poll loop. Worth making the value configurable via an env var
(
TUYA_HTTP_TIMEOUT_MS) for slow links.This is orthogonal to the existing report about
_requestnot checkingresp.ok/resp.json()— it's about the request that never completes at all rather than one that completes with a bad body.