jackwener/OpenCLI · error · CommandExecutionError
Upwork search results did not include any job with a valid c
Error message
Upwork search results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows.
What it means
A CommandExecutionError thrown when the search returned jobs but jobsToListRows produced zero rows because none of the job entries carried a valid ciphertext id. The CLI requires round-trippable ids so each list row can be opened with the detail command, and it refuses to emit rows that cannot be resolved later.
Source
Thrown at clis/upwork/search.js:111
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.');
}
return rows;
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect a job object from window.__NUXT__.state.jobsSearch.jobs[0] in DevTools to find where the ciphertext id now lives.
- Update jobsToListRows' id extraction to the new field name/path.
- Retry after a full reload in case a mixed old/new page render produced malformed cards.
- If only some jobs lack ids, the error means ALL did - confirm you weren't hitting a test/experimental search variant.
Example fix
// before const id = job.obscuredId // undefined after schema change -> row skipped // after const id = job.obscuredId || job.ciphertext || job.id; // fall back across known id fields before skipping
Defensive patterns
Strategy: type-guard
Validate before calling
// check ids exist before building rows
const allHaveIds = jobs.every(j =>
j && typeof j === 'object' &&
typeof (j.obscuredId || j.ciphertext || j.id) === 'string' &&
(j.obscuredId || j.ciphertext || j.id).length > 0);
if (!allHaveIds) throw new Error('Job payloads lack ciphertext ids; update extraction'); Type guard
function hasCiphertextId(job) {
const id = job && (job.obscuredId || job.ciphertext || job.id);
return typeof id === 'string' && id.length > 0;
} Try / catch
try {
rows = await cli.search(query);
} catch (e) {
if (String(e.message).includes('valid ciphertext id')) {
await dumpFirstJobObject(); // inspect schema, then fix id extraction
throw e;
} else throw e;
} Prevention
- Pin-test one known job object's shape after Upwork deploys.
- Support multiple known id field names (obscuredId, ciphertext, id) in extraction.
- Never emit rows without ids - keep the round-trip guarantee intact.
- Check DevTools for promoted/featured card variants that carry ids differently.
When it happens
Trigger: Running upwork search when every job object in the payload lacks the expected ciphertext id field - typically because Upwork changed the job object schema or the id extraction regex/field name no longer matches.
Common situations: An Upwork API/SSR change altering how job identifiers (e.g. ~01abc... ciphertexts) are embedded in the state; promoted/featured job cards using a different object shape; parsing jobsToListRows failing on a new card layout.
Related errors
- Upwork search state had an unexpected jobs shape; expected w
- Barchart greeks returned an unreadable options payload${data
- Cannot resolve aid for bvid: ${bvid}
- Bilibili reply add API did not return rpid for the posted co
- coingecko global returned no data envelope
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/df4f476893c848f0.
Report an issue: GitHub.