lissy93/web-check · error · Error

Received non-success response code: ${responseCode}

Error message

Received non-success response code: ${responseCode}

What it means

After the raw HTTP request completes, statusHandler checks the response code and throws unless it is in 200-399. This deliberately treats any 4xx/5xx (and anything below 200) as a hard failure, because timing a response the server refused is not meaningful for status reporting of a healthy site.

Source

Thrown at api/status.js:43

    startTime = performance.now();
    const response = await new Promise((resolve, reject) => {
      const req = https.get(url, { headers: { 'user-agent': UA } }, (res) => {
        let data = '';
        responseCode = res.statusCode;
        res.on('data', (chunk) => {
          data += chunk;
        });
        res.on('end', () => {
          resolve(res);
        });
      });

      req.on('error', reject);
      req.end();
    });

    if (responseCode < 200 || responseCode >= 400) {
      throw new Error(`Received non-success response code: ${responseCode}`);
    }

    performance.mark('B');
    performance.measure('A to B', 'A', 'B');
    let responseTime = performance.now() - startTime;
    obs.disconnect();

    return { isUp: true, dnsLookupTime, responseTime, responseCode };
  } catch (error) {
    obs.disconnect();
    throw error;
  }
};

export const handler = middleware(statusHandler);
export default handler;

View on GitHub (pinned to af1a97759f)

Solutions

  1. Confirm the target responds 2xx/3xx with curl -I and the same User-Agent the checker uses
  2. If the 4xx is bot protection (403/429), adjust headers/UA or rate limiting on the caller side
  3. Treat this as expected signal rather than a bug: report the code to your users instead of crashing

Example fix

// before
const r = await fetch('https://example.com/api/status?url=https://example.com/deleted-page');

// after
const target = 'https://example.com/';
const probe = await fetch(target, { method: 'HEAD', redirect: 'follow' });
if (!probe.ok) console.warn(`target returned ${probe.status}, checker will fail`);
const r = await fetch(`https://example.com/api/status?url=${encodeURIComponent(target)}`);
Defensive patterns

Strategy: try-catch

Validate before calling

const probe = await fetch(url, { method: 'HEAD', redirect: 'follow' });
if (probe.status < 200 || probe.status >= 400) skipStatusCheck(`target already returns ${probe.status}`);

Type guard

null

Try / catch

try { const timing = await statusHandler(url); }
catch (e) {
  if (/non-success response code/.test(e.message)) return { ok: false, reason: e.message };
  throw e;
}

Prevention

When it happens

Trigger: Target returns 404, 403 (bot-blocked), 500, 503; or non-standard codes below 200. Redirects (3xx) are accepted; 4xx/5xx are not.

Common situations: Screenshot-scanner targets behind WAFs that 403 unknown agents, temporarily down origin servers returning 5xx, typo'd paths returning 404, or CDN rate-limit responses (429).


AI-assisted analysis of lissy93/web-check@af1a97759f (2026-08-27). Data as JSON: /api/errors/4c346e802d44f6f3. Report an issue: GitHub.