santifer/career-ops · error · Error

the release pointer names an unusable index filename (${JSON

Error message

the release pointer names an unusable index filename (${JSON.stringify(doc.filename)}): ${url}

What it means

The pointer is a valid JSON object but its filename field is missing or fails FILENAME_RE, the plugin's whitelist regex for index filenames. Because the filename is used to build a download URL, the plugin refuses any name it cannot validate, and echoes the offending value via JSON.stringify. This prevents path injection or SSRF via a hostile pointer.

Source

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

  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 };
}

/**
 * Stream the asset to `tmpFile`, hashing as it goes, and return the digest.
 *
 * Streamed rather than buffered: the body is millions of times the size of
 * anything else this plugin reads, and readBoundedText's 1 MiB ceiling exists

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. curl the pointer URL and inspect the filename value; compare it against the expected index-name pattern used by your installed plugin version.
  2. Upgrade (or downgrade) the plugin so its FILENAME_RE matches the pointer format published by your endpoint — a version mismatch is the usual cause.
  3. If you publish the pointer, regenerate it with a filename matching the plugin's expected pattern (no slashes, correct extension).
  4. Restore the default endpoint (unset H1B_API_BASE) if the custom host publishes an incompatible schema.

Example fix

// before (pointer contents)
{"filename":"../../etc/h1b-index.json","sha256":"..."}
// after
{"filename":"h1b-index-2026-08-30.json","sha256":"<64-hex>"}
Defensive patterns

Strategy: validation

Validate before calling

const doc = JSON.parse(await (await fetch(pointerUrl)).text());
const FILENAME_RE = /^[\w.-]+\.json$/;
if (!FILENAME_RE.test(String(doc?.filename ?? ''))) {
  throw new Error(`pointer filename ${JSON.stringify(doc?.filename)} will be rejected; use a flat index filename`);
}

Type guard

function hasUsableIndexFilename(doc) {
  return !!doc && typeof doc === 'object' && typeof doc.filename === 'string' && /^[\w.-]+\.json$/.test(doc.filename);
}

Try / catch

try {
  await installH1BIndex();
} catch (e) {
  if (String(e.message).includes('unusable index filename')) {
    console.error('Pointer filename failed the allowlist regex; align endpoint schema with the plugin version.');
  } else throw e;
}

Prevention

When it happens

Trigger: fetchPointer(url) parses a JSON object whose doc.filename is undefined, empty, or does not match FILENAME_RE (e.g. contains slashes, '../', unexpected extensions).

Common situations: A custom H1B_API_BASE serves a pointer schema from a different/older plugin version whose filename format differs; the pointer object uses a different key (e.g. 'file' or 'asset'); a compromised or mispublished pointer names a non-index file.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — 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/936605d059375eb8. Report an issue: GitHub.