santifer/career-ops · error · Error

hackernews: could not find "Ask HN: Who is hiring?" thread i

Error message

hackernews: could not find "Ask HN: Who is hiring?" thread in search results

What it means

Thrown by hackernews fetch() when resolveLatestThreadId(searchData) returns null after querying the Algolia HN search API (filtered to tags=story,author_whoishiring). It means the search returned no usable monthly 'Ask HN: Who is hiring?' thread id. The provider searches by the whoishiring account tag precisely so a free-text query cannot surface an unrelated story; a null result therefore points at a data/availability problem, not a ranking problem.

Source

Thrown at providers/hackernews.mjs:153

  const RE = /ask\s+hn[:\s]+who\s+is\s+hiring/i;
  for (const hit of hits) {
    if (hit && typeof hit.objectID === 'string' && typeof hit.title === 'string') {
      if (RE.test(hit.title)) return hit.objectID;
    }
  }
  return null;
}

/** @type {Provider} */
export default {
  id: 'hackernews',

  async fetch(entry, ctx) {
    // Step 1: Find the latest "Who is hiring?" story id.
    const searchData = await ctx.fetchJson(SEARCH_URL, { redirect: 'error' });
    const threadId = resolveLatestThreadId(searchData);
    if (!threadId) {
      throw new Error('hackernews: could not find "Ask HN: Who is hiring?" thread in search results');
    }

    const threadHnUrl = `https://news.ycombinator.com/item?id=${threadId}`;

    // Step 2: Fetch the thread item (children = top-level job comments).
    const item = await ctx.fetchJson(itemUrl(threadId), { redirect: 'error' });
    if (!item || typeof item !== 'object') {
      throw new Error(`hackernews: unexpected item response for thread ${threadId}`);
    }

    const children = /** @type {any} */ (item).children;
    if (!Array.isArray(children)) return [];

    // Step 3: Parse each comment.
    const jobs = [];
    for (const child of children) {
      // Skip deleted / dead / empty comments.
      if (!child || child.deleted || child.dead) continue;

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Retry on the next scan run (the thread typically appears within the first few days of the month).
  2. Verify the search endpoint directly: open https://hn.algolia.com/api/v1/search_by_date?tags=story,author_whoishiring&hitsPerPage=5 in a browser and confirm hits[] is populated.
  3. If Algolia is persistently down, temporarily disable the hackernews board entry (enabled: false) until it recovers.
  4. Check that ctx.fetchJson is not silently returning a cached/empty body from a proxy.
Defensive patterns

Strategy: retry

Validate before calling

// Probe the Algolia search endpoint before driving the provider.
const probe = await ctx.fetchJson(SEARCH_URL, { redirect: 'error' });
if (!Array.isArray(probe?.hits) || probe.hits.length === 0) {
  console.warn('hackernews: search index unavailable this run — skipping');
  continue;
}

Type guard

/** Algolia search response carrying at least one whoishiring story. */
function hasHiringHits(json) {
  return !!json && typeof json === 'object'
    && Array.isArray(json.hits) && json.hits.length > 0
    && json.hits.some(h => h && typeof h.objectID === 'string');
}

Try / catch

for (let attempt = 0; attempt < 2; attempt++) {
  try {
    return await hackernewsProvider.fetch(entry, ctx);
  } catch (err) {
    const transient = /could not find .* thread in search results/.test(err.message);
    if (!transient || attempt === 1) throw err;
    await new Promise(r => setTimeout(r, 5000)); // back off, then retry once
  }
}

Prevention

When it happens

Trigger: Algolia's HN index is lagging or temporarily unavailable (5xx/empty hits); it is the very start of a month before the whoishiring account has posted the new thread; a network/timeout error returned a 200 with a degenerate body; the Algolia tags query changed behaviour. Since the lookup is filtered to the whoishiring author, a null hit means that author's thread genuinely is not in the returned hits.

Common situations: Running a scan in the first days of a new month before the thread is live; transient Algolia outage or rate limiting; a corporate proxy returning an HTML interstitial parsed as JSON; DNS/connectivity failure to hn.algolia.com.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/35ab688c10e199bb. Report an issue: GitHub.