{"record":{"id":"332ce4bb78124e0b","repo":"santifer/career-ops","slug":"the-release-pointer-is-not-an-object-url","errorCode":null,"errorMessage":"the release pointer is not an object: ${url}","messagePattern":"the release pointer is not an object: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/h1b-sponsor/install-h1b-index.mjs","lineNumber":118,"sourceCode":" * them is about to become part of a URL and the other the sole thing standing\n * between a substituted download and a lookup that trusts it.\n */\nasync function fetchPointer(fetchImpl, url) {\n  const out = await fetchImpl(url, { timeoutMs: POINTER_TIMEOUT_MS }, async res => {\n    if (res.status !== 200) return { status: res.status };\n    const read = await readBoundedText(res, MAX_POINTER_BYTES);\n    return read.oversized ? { oversized: true } : { text: read.text };\n  });\n  if (out.status) throw new Error(`could not read the release pointer (HTTP ${out.status}): ${url}`);\n  if (out.oversized) throw new Error(`the release pointer is implausibly large: ${url}`);\n\n  let doc;\n  try {\n    doc = JSON.parse(String(out.text || ''));\n  } catch {\n    throw new Error(`the release pointer is not JSON: ${url}`);\n  }\n  if (!doc || typeof doc !== 'object') throw new Error(`the release pointer is not an object: ${url}`);\n\n  const filename = String(doc.filename || '');\n  if (!FILENAME_RE.test(filename)) {\n    throw new Error(`the release pointer names an unusable index filename (${JSON.stringify(doc.filename)}): ${url}`);\n  }\n  const sha256 = String(doc.sha256 || '').trim().toLowerCase();\n  if (!SHA256_RE.test(sha256)) {\n    throw new Error(`the release pointer does not carry a sha256 digest: ${url}`);\n  }\n  // Recorded, never acted on, so a missing or odd value costs a label rather\n  // than the install. Bounded because it lands in a file on disk.\n  const version = doc.version === undefined || doc.version === null\n    ? null\n    : String(doc.version).slice(0, 64);\n  return { filename, sha256, version };\n}\n\n/**","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/plugins/h1b-sponsor/install-h1b-index.mjs#L100-L136","documentation":"The release pointer parsed as JSON but is not an object (e.g. a JSON string, number, array, or the literal 'null'). fetchPointer() requires a JSON object so it can read doc.filename and doc.sha256; anything else is rejected with this error. This guards against a pointer file whose contents silently changed shape.","triggerScenarios":"fetchPointer(url) parses the body successfully but the result is falsy or typeof doc !== 'object' — e.g. the file contains \"null\", \"42\", \"[1,2]\", or a quoted string.","commonSituations":"The pointer file was overwritten with a placeholder or checksum value during a broken release; someone hand-edited the hosted pointer; the endpoint serves a JSON scalar from a different service; an empty-ish body like 'null' after upstream cleared the file.","solutions":["Inspect the pointer file at the URL (curl it) and confirm it is a JSON object like {\"filename\":...,\"sha256\":...}.","Repoint H1B_API_BASE to the correct host if you are hitting the wrong service.","If you control the release, republish a correctly shaped pointer object and retry."],"exampleFix":"// before (pointer file contents)\n\"0.9.4\"\n// after\n{\"filename\":\"h1b-index-2026-08-30.json\",\"sha256\":\"<64-hex>\"}","handlingStrategy":"validation","validationCode":"const doc = JSON.parse(await (await fetch(pointerUrl)).text());\nif (!doc || typeof doc !== 'object' || Array.isArray(doc)) {\n  throw new Error(`pointer at ${pointerUrl} must be a JSON object with filename/sha256`);\n}","typeGuard":"function isPointerObject(v) {\n  return !!v && typeof v === 'object' && !Array.isArray(v) && typeof v.filename === 'string';\n}","tryCatchPattern":"try {\n  await installH1BIndex();\n} catch (e) {\n  if (String(e.message).includes('not an object')) {\n    console.error('Pointer file has the wrong JSON shape; republish as {filename, sha256}.');\n  } else throw e;\n}","preventionTips":["Publish pointers only as JSON objects — never scalars, arrays, or null placeholders.","Add a release- CI step that validates the pointer shape before publishing.","Don't hand-edit hosted pointer files; regenerate them via the release script.","Pin plugin and endpoint versions so pointer schemas stay aligned."],"tags":["json","validation","schema"],"backgroundTag":"invalid-json-response","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}