Skip to content

Add a request timeout to fetch calls — commands hang indefinitely on a stalled connection #5

Description

@848plus

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions