{"record":{"id":"71f35a2d36f87037","repo":"jackwener/OpenCLI","slug":"indeed-job-page-did-not-expose-detail-or-error-mar","errorCode":null,"errorMessage":"Indeed job page did not expose detail or error markers within 15s","messagePattern":"Indeed job page did not expose detail or error markers within 15s","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/indeed/job.js","lineNumber":69,"sourceCode":"                const location = document.querySelector('[data-testid=\"jobsearch-JobInfoHeader-companyLocation\"] div, [data-testid=\"inlineHeader-companyLocation\"]')?.textContent?.trim() ?? '';\n                const salary = document.querySelector('[id*=\"salaryInfoAndJobType\"] span, [data-testid=\"job-salary\"]')?.textContent?.trim() ?? '';\n                const jobType = Array.from(document.querySelectorAll('[id*=\"salaryInfoAndJobType\"] span, [data-testid=\"job-type\"]'))\n                    .map(s => (s.textContent || '').trim())\n                    .filter(t => t && t !== salary)\n                    .join(', ');\n                const description = document.querySelector('#jobDescriptionText')?.innerText?.trim() ?? '';\n                return { ready, challenge, notFound, title, company, location, salary, jobType, description };\n            })()`);\n        }\n        catch (e) {\n            throw new CommandExecutionError(`Failed to scrape Indeed job detail DOM: ${e?.message ?? e}`, 'The page may not have fully loaded; try again.');\n        }\n\n        if (detail?.challenge) {\n            throw new CommandExecutionError('Indeed served a Cloudflare challenge page', 'Open https://www.indeed.com in the connected browser and clear the challenge, then retry.');\n        }\n        if (!detail?.ready) {\n            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.');\n        }\n        if (detail?.notFound || (!detail?.title && !detail?.description)) {\n            throw new EmptyResultError('indeed job', `No Indeed job posting found for jk \"${jk}\"`);\n        }\n\n        return [{\n            id: jk,\n            title: detail.title.replace(/\\s+/g, ' ').trim(),\n            company: detail.company.replace(/\\s+/g, ' ').trim(),\n            location: detail.location.replace(/\\s+/g, ' ').trim(),\n            salary: detail.salary.replace(/\\s+/g, ' ').trim(),\n            job_type: detail.jobType.replace(/\\s+/g, ' ').trim(),\n            description: detail.description,\n            url,\n        }];\n    },\n});\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/indeed/job.js#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before calling, confirm the URL is a live Indeed job page\nconst res = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });\nif (!res || res.status() >= 400) throw new Error('Job URL not reachable');","typeGuard":null,"tryCatchPattern":"try {\n  const job = await indeed.job(jk);\n} catch (e) {\n  if (e.message.includes('within 15s')) {\n    // retry once after a pause; if it persists, flag as DOM/timeout issue\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["timeout","scraping","dom","page-load"],"backgroundTag":"scrape-readiness-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}