jackwener/OpenCLI · error · CommandExecutionError
Upwork search state (window.__NUXT__.state.jobsSearch) was n
Error message
Upwork search state (window.__NUXT__.state.jobsSearch) was not present within 15s
What it means
A CommandExecutionError thrown when the Browser Bridge poll completes but window.__NUXT__.state.jobsSearch never appeared within the 15s timeout (payload.ready false). The page loaded enough to not redirect or challenge, but the SSR/hydration state for the jobs search never materialized. The library gives up after 15 seconds rather than hanging.
Source
Thrown at clis/upwork/search.js:94
jobsPresent: !!(state && Object.prototype.hasOwnProperty.call(state, 'jobs')),
jobs: state ? state.jobs : undefined,
paging: state && state.paging ? state.paging : null,
status: state ? state.status : null,
};
})()`));
}
catch (e) {
throw new CommandExecutionError(`Failed to read Upwork search state: ${e?.message ?? e}`, 'The Nuxt state global was not reachable; try again after opening Upwork in the connected browser.');
}
if (payload?.onLogin) {
throw new AuthRequiredError('upwork.com', 'Upwork redirected to login. Open https://www.upwork.com in the connected browser and sign in, then retry.');
}
if (payload?.challenge) {
throw new CommandExecutionError('Upwork served a Cloudflare challenge page', 'Open https://www.upwork.com in the connected browser and clear the challenge, then retry.');
}
if (!payload?.ready) {
throw new CommandExecutionError('Upwork search state (window.__NUXT__.state.jobsSearch) was not present within 15s', 'The page may not have finished hydrating, or the SSR state shape may have changed.');
}
if (!isPlainObject(payload)) {
throw new CommandExecutionError('Upwork search returned an unexpected Browser Bridge payload shape');
}
if (!payload.jobsPresent || !Array.isArray(payload.jobs)) {
throw new CommandExecutionError('Upwork search state had an unexpected jobs shape; expected window.__NUXT__.state.jobsSearch.jobs to be an array.');
}
const jobs = payload.jobs;
if (jobs.length === 0) {
throw new EmptyResultError('upwork search', `No Upwork jobs matched "${query}"${location ? ` in ${location}` : ''}`);
}
const offset = (pageNum - 1) * perPage;
const rows = jobsToListRows(jobs, { offset, limit: perPage });
if (rows.length === 0) {
throw new CommandExecutionError('Upwork search results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows.');
}View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command once the page has fully finished loading in the connected browser.
- Verify the connected tab is actually on an Upwork jobs search results page.
- If it reproduces on a fully loaded page, inspect window.__NUXT__.state in DevTools to see if the jobsSearch key moved - update the CLI's expectations if Upwork changed shape.
- Improve network/CPU conditions (close heavy tabs, faster connection) and increase patience before retrying.
Example fix
// before
await cli.search('vue developer') // throws: state not present within 15s
// after
await page.waitForFunction(() => window.__NUXT__?.state?.jobsSearch, { timeout: 30000 }); // or retry the command after full load
await cli.search('vue developer') Defensive patterns
Strategy: retry
Validate before calling
// wait for hydration before invoking, or confirm the page is a search results page
await page.waitForFunction(() => !!(window.__NUXT__ && window.__NUXT__.state), { timeout: 30000 });
if (!location.pathname.includes('/jobs')) throw new Error('Navigate to an Upwork jobs search page first'); Type guard
function isNuxtStateReady(win) {
return !!(win && win.__NUXT__ && win.__NUXT__.state &&
typeof win.__NUXT__.state === 'object');
} Try / catch
try {
rows = await cli.search(query);
} catch (e) {
if (String(e.message).includes('was not present within 15s')) {
await waitForHydration(60000); // give the page more time
rows = await cli.search(query); // retry once
} else throw e;
} Prevention
- Run searches against a fully loaded page on a reliable connection.
- Confirm the tab is on a real jobs search results URL, not an intermediate page.
- Inspect window.__NUXT__.state after Upwork deploys; key renames break readiness checks.
- Close CPU-heavy tabs so hydration completes within the timeout.
When it happens
Trigger: Running upwork search against a page that hydrates slowly, a page where Upwork changed the __NUXT__ state shape so jobsSearch no longer exists, or a search URL that renders no jobsSearch state (e.g. not actually on a search results page).
Common situations: Slow network or heavy page causing hydration past 15s; an Upwork frontend update renaming/moving jobsSearch in the Nuxt payload; landing on a login-adjacent or error page that still isn't a challenge; CPU-starved browser taking long to hydrate.
Related errors
- Upwork feed state (window.__NUXT__.state.${stateKey}) was no
- Ctrip place page did not render attraction links for city id
- Ctrip bus page did not render schedule rows (state=${String(
- Ctrip cruise page did not render (state=${String(indexWait)}
- Ctrip round-trip flight page did not render flight cards (st
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ee3a230dba4ece90.
Report an issue: GitHub.