jackwener/OpenCLI · error · CommandExecutionError
Indeed job page did not expose detail or error markers withi
Error message
Indeed job page did not expose detail or error markers within 15s
What it means
Thrown when the job detail page's DOM never exposes either the detail payload or the known error markers within the 15s polling window (detail.ready stays falsy). The library polls for readiness markers; if neither success nor failure markers appear, it gives up with this error.
Source
Thrown at clis/indeed/job.js:69
const location = document.querySelector('[data-testid="jobsearch-JobInfoHeader-companyLocation"] div, [data-testid="inlineHeader-companyLocation"]')?.textContent?.trim() ?? '';
const salary = document.querySelector('[id*="salaryInfoAndJobType"] span, [data-testid="job-salary"]')?.textContent?.trim() ?? '';
const jobType = Array.from(document.querySelectorAll('[id*="salaryInfoAndJobType"] span, [data-testid="job-type"]'))
.map(s => (s.textContent || '').trim())
.filter(t => t && t !== salary)
.join(', ');
const description = document.querySelector('#jobDescriptionText')?.innerText?.trim() ?? '';
return { ready, challenge, notFound, title, company, location, salary, jobType, description };
})()`);
}
catch (e) {
throw new CommandExecutionError(`Failed to scrape Indeed job detail DOM: ${e?.message ?? e}`, 'The page may not have fully loaded; try again.');
}
if (detail?.challenge) {
throw new CommandExecutionError('Indeed served a Cloudflare challenge page', 'Open https://www.indeed.com in the connected browser and clear the challenge, then retry.');
}
if (!detail?.ready) {
throw new CommandExecutionError('Indeed job page did not expose detail or error markers within 15s', 'Indeed may still be loading or the DOM shape may have changed; retry after opening Indeed in the connected browser.');
}
if (detail?.notFound || (!detail?.title && !detail?.description)) {
throw new EmptyResultError('indeed job', `No Indeed job posting found for jk "${jk}"`);
}
return [{
id: jk,
title: detail.title.replace(/\s+/g, ' ').trim(),
company: detail.company.replace(/\s+/g, ' ').trim(),
location: detail.location.replace(/\s+/g, ' ').trim(),
salary: detail.salary.replace(/\s+/g, ' ').trim(),
job_type: detail.jobType.replace(/\s+/g, ' ').trim(),
description: detail.description,
url,
}];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Retry — the page may simply have needed more time to load
- Open the job page in the connected browser to confirm it renders, then retry
- Increase the polling timeout beyond 15s if you regularly see slow loads
- Refresh the connected browser tab or restart the browser session
- Check whether Indeed changed their DOM markers and update the readiness detection
Defensive patterns
Strategy: retry
Validate before calling
// before calling, confirm the URL is a live Indeed job page
const res = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
if (!res || res.status() >= 400) throw new Error('Job URL not reachable'); Try / catch
try {
const job = await indeed.job(jk);
} catch (e) {
if (e.message.includes('within 15s')) {
// retry once after a pause; if it persists, flag as DOM/timeout issue
}
throw e;
} Prevention
- Run on a stable/fast network connection
- Pre-warm the page with a browser navigation before the command
- Increase timeout if your environment is consistently slow
- Verify readiness markers still match Indeed's current DOM
When it happens
Trigger: After the challenge check, detail?.ready is false — the evaluate()'s ready flag never became true because neither the job detail elements nor the not-found markers rendered in time.
Common situations: Very slow network or heavy page assets delaying render; Indeed layout change removed the readiness markers; page stuck on a loader/spinner; navigation halted by the connected browser being busy.
Related errors
- Indeed search page did not expose result or empty-state mark
- IMDb search results did not finish loading
- Title page did not finish loading: ${id}
- Failed to scrape Indeed job detail DOM: ${e?.message ?? e}
- Failed to scrape Indeed search DOM: ${e?.message ?? e}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/71f35a2d36f87037.
Report an issue: GitHub.