santifer/career-ops · warning
archive render skipped — Greenhouse API unreachable
Error message
archive render skipped — Greenhouse API unreachable
What it means
The archive-render test needs a live job URL to exercise archive-posting.mjs; it fetches the public Greenhouse board API for a known board. If the fetch fails, returns no usable job URL, or the URL's host is not in the allowed greenhouse host set, the test warns and skips rendering instead of failing on a network condition.
Solutions
- Verify network access: `curl https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false` — if it fails, fix connectivity/proxy (set HTTPS_PROXY) and rerun.
- Re-run later: Greenhouse outages are transient; the test is designed to skip, not fail.
- If the pinned board reliably returns nothing, point the test at a different stable Greenhouse board.
- Accept the skip when developing offline — no repo code is at fault.
Example fix
// before
const res = await fetch('https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false');
// after
const res = await fetch(process.env.ARCHIVE_TEST_BOARD_URL || 'https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false'); Defensive patterns
Strategy: retry
Validate before calling
let reachable = false; try { const r = await fetch('https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false'); reachable = r.ok; } catch {} if (!reachable) console.warn('Greenhouse unreachable; archive render test will skip'); Type guard
const isAllowedJobUrl = (u) => { try { const p = new URL(u); return p.protocol === 'https:' && ['boards.greenhouse.io','job-boards.greenhouse.io'].includes(p.hostname); } catch { return false; } }; Try / catch
try { const res = await fetch(boardUrl); const { jobs } = await res.json(); liveJobUrl = jobs?.[0]?.absolute_url ?? null; } catch { warn('archive render skipped — Greenhouse API unreachable'); } Prevention
- Configure proxy env vars (HTTPS_PROXY) when behind a corporate firewall
- Treat external-API-dependent tests as skippable-by-design and retry in CI
- Pin an alternate fallback board in case the known board empties
- Check the API manually with curl when the warning repeats
When it happens
Trigger: `fetch('https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false')` throws (offline, DNS failure, proxy), or the response contains no jobs[0].absolute_url, or the candidate URL's hostname is not boards.greenhouse.io / job-boards.greenhouse.io.
Common situations: Running the suite offline or behind a corporate proxy blocking external APIs, Greenhouse API rate limiting or the board being emptied, or the known board changing so no candidates are returned.
Related errors
- All active models failed. Last error
- arbeitsagentur: all keyword request(s) failed
- himalayas: unexpected API response - expected
- HTTP
- justjoin: unexpected API response — expected
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/2c3fd065c2386a33.
Report an issue: GitHub.
Appendix: source
Thrown at test-all.mjs:7137
} catch { /* playwright not installed */ }
if (!hasBrowser) {
warn('archive render skipped — no Playwright browser in env');
} else {
let liveJobUrl = null;
try {
const res = await fetch('https://boards-api.greenhouse.io/v1/boards/anthropic/jobs?content=false');
const { jobs } = await res.json();
const candidate = jobs?.[0]?.absolute_url ?? null;
if (candidate) {
const u = new URL(candidate);
const allowed = new Set(['boards.greenhouse.io', 'job-boards.greenhouse.io']);
if (u.protocol === 'https:' && allowed.has(u.hostname)) liveJobUrl = candidate;
}
} catch { /* offline — degrade gracefully */ }
if (!liveJobUrl) {
warn('archive render skipped — Greenhouse API unreachable');
} else {
const JDS_DIR = join(ROOT, 'jds');
const startedAt = Date.now();
const archiveOut = run('node', ['archive-posting.mjs', liveJobUrl], { timeout: 60000 });
if (archiveOut === null) {
fail('live archive: script exited non-zero on live URL');
} else {
pass('live archive: exited 0');
const recent = existsSync(JDS_DIR)
? readdirSync(JDS_DIR)
.filter(f => f.endsWith('.pdf'))
.filter(f => statSync(join(JDS_DIR, f)).mtimeMs >= startedAt)
: [];
if (recent.length === 0) {
fail('live archive: no PDF written to jds/ during test run');View on GitHub (pinned to e7abd431fc)