pbakaus/impeccable · error

TypeError: fetch failed: {}

Error message

TypeError: fetch failed: {}

What it means

The HTTP request from generate-image to the OpenAI image API failed at the transport level (ureq returned a non-status error). The command formats it as a Node-style "TypeError: fetch failed" and exits 1. This is a connectivity problem, not an HTTP error response from the API.

Source

Thrown at crates/context/src/generate_image.rs:357

        m.insert("model".into(), Value::String("gpt-image-2".into()));
        m.insert("prompt".into(), Value::String(prompt.clone()));
        m.insert("size".into(), Value::String(size.clone()));
        m.insert("quality".into(), Value::String(quality.clone()));
        m.insert("n".into(), Value::from(1));
        agent
            .post("https://api.openai.com/v1/images/generations")
            .set("Authorization", &format!("Bearer {}", key))
            .set("content-type", "application/json")
            .send_string(&serde_json::to_string(&Value::Object(m)).unwrap())
    };
    let (status, text) = match response {
        Ok(r) => {
            let st = r.status();
            (st, r.into_string().unwrap_or_default())
        }
        Err(ureq::Error::Status(code, r)) => (code, r.into_string().unwrap_or_default()),
        Err(e) => {
            io.err(&format!("TypeError: fetch failed: {}\n", e));
            return 1;
        }
    };
    if !(200..300).contains(&status) {
        let snippet: String = text.chars().take(300).collect();
        io.err(&format!("generate-image: API error {}: {}\n", status, snippet));
        return 1;
    }
    let json: Value = serde_json::from_str(&text).unwrap_or(Value::Null);
    let b64 = json.get("data").and_then(|d| d.get(0)).and_then(|d| d.get("b64_json")).and_then(|b| b.as_str()).filter(|s| !s.is_empty());
    let Some(b64) = b64 else {
        io.err("generate-image: no image in response\n");
        return 1;
    };
    let bytes = base64_decode(b64);
    let _ = std::fs::write(abs(&out), bytes);
    // best-effort embed + sidecar
    // JS-PARITY: generate-image.mjs#676 reports whether the embed actually

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Check network connectivity: `curl -sS https://api.openai.com/v1/models -o /dev/null -w '%{http_code}'`.
  2. Verify proxy settings (HTTPS_PROXY/HTTP_PROXY) are correct if behind a corporate proxy, and that the CA bundle is available for TLS.
  3. Retry after confirming the network/VPN is up — transient DNS or connection failures resolve on their own.
  4. Inspect the printed underlying ureq error for the specific cause (DNS, connect, TLS) and fix accordingly.
  5. If in a container/sandbox, ensure outbound HTTPS egress to api.openai.com is allowed.

Example fix

// before
impeccable generate-image --prompt "..." --out o.png
// TypeError: fetch failed: dns error: ...
// after
export HTTPS_PROXY=http://proxy.corp:8080
impeccable generate-image --prompt "..." --out o.png   # or run on a network with egress
Defensive patterns

Strategy: retry

Validate before calling

// preflight reachability
const ok = spawnSync("curl", ["-sS", "-o", "/dev/null", "-w", "%{http_code}", "https://api.openai.com/v1/models"]).status === 0;
if (!ok) console.warn("api.openai.com unreachable; generate-image will fail");

Try / catch

for (let attempt = 1; attempt <= 3; attempt++) {
  const r = spawnSync("impeccable", ["generate-image", ...], { encoding: "utf8" });
  if (r.status === 0) break;
  if (r.stderr.includes("TypeError: fetch failed") && attempt < 3) {
    await new Promise(res => setTimeout(res, 2 ** attempt * 1000));
    continue;
  }
  throw new Error(r.stderr);
}

Prevention

When it happens

Trigger: `ureq::Error` that is neither a status response nor a transport-success — DNS resolution failure, connection refused/timeout, TLS certificate error, proxy misconfiguration, or no network interface while POSTing to the images endpoint.

Common situations: Corporate proxy/firewall blocking api.openai.com; laptop offline or VPN down; DNS issues in containers; system clock skew causing TLS failures; IPv6-only environments that can't reach the endpoint.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/d2ee07ca320f5d8c. Report an issue: GitHub.