MagicMirrorOrg/MagicMirror · warning

${this.logContext}${this.#shortenUrl()} - ${message} Retry #

Error message

${this.logContext}${this.#shortenUrl()} - ${message} Retry #${this.networkErrorCount} in ${Math.round(nextDelay / 1000)}s.

What it means

In HTTPFetcher.fetch, when a network-level error occurs (fetch rejection such as DNS failure, connection refused/reset, timeout), the fetcher computes an exponential backoff via calculateBackoffDelay capped at reloadInterval, logs a retry message as warning for the first two attempts and error afterwards, and increments networkErrorCount for each subsequent retry.

Source

Thrown at js/http_fetcher.js:330

				this.emit("error", errorInfo);
			}
		} catch (error) {
			const isTimeout = error.name === "AbortError";
			const message = isTimeout ? `Request timeout after ${this.timeout}ms` : `Network error: ${error.message}`;

			this.networkErrorCount = Math.min(this.networkErrorCount + 1, this.maxRetries);
			const exhausted = this.networkErrorCount >= this.maxRetries;

			if (exhausted) {
				nextDelay = this.reloadInterval;
				Log.error(`${this.logContext}${this.#shortenUrl()} - ${message} Max retries reached, retrying at configured interval (${Math.round(nextDelay / 1000)}s).`);
			} else {
				nextDelay = HTTPFetcher.calculateBackoffDelay(this.networkErrorCount, {
					maxDelay: this.reloadInterval
				});
				const retryMsg = `${this.logContext}${this.#shortenUrl()} - ${message} Retry #${this.networkErrorCount} in ${Math.round(nextDelay / 1000)}s.`;
				if (this.networkErrorCount <= 2) {
					Log.warn(retryMsg);
				} else {
					Log.error(retryMsg);
				}
			}

			const errorInfo = this.#createErrorInfo(
				message,
				null,
				"NETWORK_ERROR",
				nextDelay,
				error
			);
			this.emit("error", errorInfo);
		} finally {
			clearTimeout(timeoutId);
		}

		this.scheduleNextFetch(nextDelay);

View on GitHub (pinned to 4b4a59534f)

Solutions

  1. Verify network connectivity from the mirror host (ping/curl the endpoint URL).
  2. Check the shortened URL in the log for a typo or expired domain; correct the address in the module config.
  3. Increase fetch_timeout or reloadInterval if the network is slow/flaky to give retries more room.
  4. Fix DNS/proxy/firewall settings so outbound HTTPS to the endpoint works.
  5. Wait — the fetcher retries automatically with exponential backoff capped at the reload interval.

Example fix

// before
curl https://api.example.com/data  # connection refused
// after
curl https://api.correct-domain.com/data  # fix URL in module config / restore network
Defensive patterns

Strategy: retry

Validate before calling

// Before starting periodic fetches, verify reachability
async function reachable(url, timeoutMs = 5000) {
  try {
    const ctl = new AbortController();
    const t = setTimeout(() => ctl.abort(), timeoutMs);
    await fetch(url, { method: "HEAD", signal: ctl.signal });
    clearTimeout(t);
    return true;
  } catch { return false;
  }
}

Type guard

function isNetworkError(err) {
  return err instanceof TypeError || /ECONNREFUSED|ENOTFOUND|ETIMEDOUT|ECONNRESET/.test(err?.cause?.code ?? "");
}

Try / catch

try {
  const res = await fetchWithTimeout(url, 10000);
} catch (err) {
  networkErrorCount++;
  const nextDelay = Math.min(reloadInterval, 1000 * 2 ** networkErrorCount);
  Log.warn(`${url} failed (${err.cause?.code ?? err.message}); retry #${networkErrorCount} in ${nextDelay / 1000}s`);
  setTimeout(fetch, nextDelay);
}

Prevention

When it happens

Trigger: fetch() throws while requesting a remote resource — unreachable host, offline network, TLS errors, connection timeout (connect timeout set by the undici Agent's fetch_timeout) — triggering the retry/backoff path.

Common situations: WiFi drop or router reboot on a Raspberry Pi; firewalled/air-gapped networks; the remote API endpoint being down or DNS misconfigured; invalid proxy settings blocking outbound HTTPS.

Related errors


AI-assisted analysis of MagicMirrorOrg/MagicMirror@4b4a59534f (2026-08-31). Data as JSON: /api/errors/b07e2e1a3902b18d. Report an issue: GitHub.