redis/node-redis · error · Error

HTTP ${response.status}

Error message

HTTP ${response.status}

What it means

Thrown by #request when the fault-injector HTTP response is not ok. Because of the try/catch shape in the source, this is the error callers actually receive for every non-ok response — it masks the richer error 112 (which includes the body). It fires both when response.text() fails and when the throw of error 112 is caught.

Source

Thrown at packages/test-utils/lib/fault-injector/fault-injector-client.ts:226

    const controller = new AbortController();
    const timeoutId = globalThis.setTimeout(() => {
      controller.abort();
    }, timeoutMs);

    try {
      const response = await this.#fetch(url, {
        method,
        headers,
        body: payload,
        signal: controller.signal
      });

      if (!response.ok) {
        try {
          const text = await response.text();
          throw new Error(`HTTP ${response.status} - ${text}`);
        } catch {
          throw new Error(`HTTP ${response.status}`);
        }
      }

      try {
        const result = (await response.json()) as T;
        return result;
      } catch {
        throw new Error(
          `HTTP ${response.status} - Unable to parse response as JSON`
        );
      }
    } finally {
      globalThis.clearTimeout(timeoutId);
    }
  }

  /**
   * Deletes a database.

View on GitHub (pinned to 90fd0652bc)

Solutions

  1. Reproduce the exact request with curl against baseUrl to read the body the library hides
  2. Fix the underlying status cause (404 → check the id; 400 → fix the payload; 5xx → check service logs)
  3. Patch #request so the response body is surfaced (see error 112 exampleFix)

Example fix

# before — library hides the body
Error: HTTP 400

# after — reproduce manually to see why
curl -i -X POST $FI_BASE_URL/action -H 'Content-Type: application/json' -d '<your-payload>'
# then fix the request per the body, and/or patch the client
Defensive patterns

Strategy: try-catch

Validate before calling

function buildFetchWithLogging(fetchImpl: typeof fetch): typeof fetch {
  return async (input, init) => {
    const res = await fetchImpl(input, init);
    if (!res.ok) {
      const clone = res.clone();
      clone.text().then(t => console.error(`[FI] ${res.status} body:`, t)).catch(() => {});
    }
    return res;
  };
}
const fi = new FaultInjectorClient(baseUrl, buildFetchWithLogging(fetch));

Type guard

function isHttpError(e: unknown): e is Error {
  return e instanceof Error && /HTTP \d{3}/.test(e.message);
}
function httpStatusFromError(e: unknown): number | null {
  const m = e instanceof Error ? e.message.match(/HTTP (\d{3})/) : null;
  return m ? Number(m[1]) : null;
}

Try / catch

try {
  await fi.triggerAction(action);
} catch (e) {
  const status = httpStatusFromError(e);
  if (status && status >= 500) {
  } else if (status && status >= 400) {
  }
  throw e;
}

Prevention

When it happens

Trigger: Any 4xx/5xx from the fault-injector REST API (listActions, triggerAction, getActionStatus, createAndSelectDatabase, deleteDatabase). The caller sees only the status code, not the body.

Common situations: Wrong baseUrl or path; fault-injector service down; invalid action payload rejected with 400; 404 for an unknown action_id; 500 from a backend crash.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/960aca86244ac139. Report an issue: GitHub.