Hmbown/CodeWhale · error

iLink API failed: HTTP

Error message

iLink API ${endpoint} failed: HTTP ${response.status} — ${text.slice(0, 200)}

What it means

apiPost sends a POST to an iLink API endpoint and throws this Error when the HTTP response status is not ok (response.ok is false). The message embeds the endpoint, HTTP status, and the first 200 characters of the response body so the developer can see the server's error output. It is a generic guard so every non-2xx POST surfaces with enough context to diagnose.

Solutions

  1. Read the status and body excerpt in the message: 401/403 means refresh the token passed to authHeaders; 400 means fix the request body.
  2. Verify the endpoint path and API version against current iLink docs.
  3. Retry with backoff if the status is 5xx or 429 (transient server/gateway issue).
  4. Confirm network/proxy reachability of the iLink host; the request uses an AbortController timeout, so also rule out gateway truncation.

Example fix

// before: raw throw on any non-ok
throw new Error(`iLink API ${endpoint} failed: HTTP ${response.status} — ${text.slice(0, 200)}`);
// after: special-case auth expiry to refresh token then retry once
if (response.status === 401) { await refreshToken(); return apiPost(endpoint, token2, body); }
if (!response.ok) throw new Error(`iLink API ${endpoint} failed: HTTP ${response.status} — ${text.slice(0, 200)}`);
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: ensure a token exists and endpoint is absolute https
if (!token) throw new Error('missing iLink token');
new URL(endpoint); // throws early on malformed endpoint

Try / catch

try {
  const res = await apiPost(endpoint, token, body);
} catch (e) {
  if (/HTTP (429|5\d\d)/.test(e.message)) return retryWithBackoff();
  if (/HTTP 40[13]/.test(e.message)) return refreshTokenAndRetry();
  throw e;
}

Prevention

When it happens

Trigger: Any POST via apiPost where the iLink server replies with 4xx/5xx: expired or invalid token in authHeaders, malformed request body, server-side error (500), or gateway errors.

Common situations: Expired WeChat/iLink access token; wrong endpoint path after an API version change; request body failing server validation; iLink service outage or rate limiting returning 5xx.

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


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/44a7c1d7016490c1. Report an issue: GitHub.

Appendix: source

Thrown at integrations/weixin-bridge/src/lib.mjs:142

 * 通用 POST 到 iLink API。
 */
export async function apiPost({ baseUrl, endpoint, body, token, timeoutMs, signal }) {
  const url = `${baseUrl.replace(/\/+$/, "")}/${endpoint}`;
  const ms = timeoutMs || DEFAULT_API_TIMEOUT_MS;
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), ms);
  signal?.addEventListener("abort", () => controller.abort(), { once: true });

  try {
    const response = await fetch(url, {
      method: "POST",
      headers: authHeaders({ token }),
      body,
      signal: controller.signal,
    });
    const text = await response.text();
    if (!response.ok) {
      throw new Error(
        `iLink API ${endpoint} failed: HTTP ${response.status} — ${text.slice(0, 200)}`
      );
    }
    return text;
  } finally {
    clearTimeout(timer);
  }
}

/**
 * 通用 GET 到 iLink API(用于轮询扫码状态等)。
 */
export async function apiGet({ baseUrl, endpoint, token, timeoutMs, signal }) {
  const url = `${baseUrl.replace(/\/+$/, "")}/${endpoint}`;
  const ms = timeoutMs || DEFAULT_API_TIMEOUT_MS;
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), ms);
  signal?.addEventListener("abort", () => controller.abort(), { once: true });

View on GitHub (pinned to 433685b202)