santifer/career-ops · error · Error

the release pointer is not JSON: ${url}

Error message

the release pointer is not JSON: ${url}

What it means

After fetchPointer() successfully reads the release pointer, it JSON.parses the body. If parsing fails — the body is HTML, an error page, truncated text, or empty — this error is thrown with the pointer URL. The library requires the pointer to be a strict JSON document naming the index asset, and refuses to guess.

Source

Thrown at plugins/h1b-sponsor/install-h1b-index.mjs:116

 *
 * Both fields are validated before use. They come from the network, and one of
 * them is about to become part of a URL and the other the sole thing standing
 * between a substituted download and a lookup that trusts it.
 */
async function fetchPointer(fetchImpl, url) {
  const out = await fetchImpl(url, { timeoutMs: POINTER_TIMEOUT_MS }, async res => {
    if (res.status !== 200) return { status: res.status };
    const read = await readBoundedText(res, MAX_POINTER_BYTES);
    return read.oversized ? { oversized: true } : { text: read.text };
  });
  if (out.status) throw new Error(`could not read the release pointer (HTTP ${out.status}): ${url}`);
  if (out.oversized) throw new Error(`the release pointer is implausibly large: ${url}`);

  let doc;
  try {
    doc = JSON.parse(String(out.text || ''));
  } catch {
    throw new Error(`the release pointer is not JSON: ${url}`);
  }
  if (!doc || typeof doc !== 'object') throw new Error(`the release pointer is not an object: ${url}`);

  const filename = String(doc.filename || '');
  if (!FILENAME_RE.test(filename)) {
    throw new Error(`the release pointer names an unusable index filename (${JSON.stringify(doc.filename)}): ${url}`);
  }
  const sha256 = String(doc.sha256 || '').trim().toLowerCase();
  if (!SHA256_RE.test(sha256)) {
    throw new Error(`the release pointer does not carry a sha256 digest: ${url}`);
  }
  // Recorded, never acted on, so a missing or odd value costs a label rather
  // than the install. Bounded because it lands in a file on disk.
  const version = doc.version === undefined || doc.version === null
    ? null
    : String(doc.version).slice(0, 64);
  return { filename, sha256, version };
}

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. curl the pointer URL and check the raw body — confirm it is valid JSON with a filename field.
  2. Fix H1B_API_BASE / the pointer URL so it hits the real pointer file, not an HTML page.
  3. If the release host is corrupted, wait for or trigger republish of the pointer, then retry.
  4. Rule out proxy interference (VPN, corporate proxy) that injects HTML into responses.

Example fix

// before
curl $H1B_API_BASE/release-pointer.json   # -> '<html>Sign in...</html>'
// after
unset H1B_API_BASE  # fall back to the default endpoint that serves real JSON
Defensive patterns

Strategy: validation

Validate before calling

const res = await fetch(pointerUrl);
const text = await res.text();
try { JSON.parse(text); } catch { throw new Error(`${pointerUrl} is not serving JSON (got: ${text.slice(0, 80)}...)`); }

Type guard

function looksLikePointer(text) {
  try { const d = JSON.parse(text); return !!d && typeof d === 'object' && !Array.isArray(d); } catch { return false; }
}

Try / catch

try {
  await installH1BIndex();
} catch (e) {
  if (String(e.message).includes('release pointer is not JSON')) {
    console.error('Endpoint returned a non-JSON body (HTML login page, proxy, or truncation). Inspect with curl.');
  } else throw e;
}

Prevention

When it happens

Trigger: fetchPointer(url) gets HTTP 200 within the byte cap, but JSON.parse(String(out.text || '')) throws because the body is not valid JSON.

Common situations: The endpoint returns an HTML login/captcha page with status 200; a captive portal or corporate proxy rewrites the response; the pointer file on the release host was truncated or corrupted; H1B_API_BASE points at the wrong path that serves plain text.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01). Data as JSON: /api/errors/99b3664cd6abe959. Report an issue: GitHub.