{"record":{"id":"cc22cc83feccb33e","repo":"jackwener/OpenCLI","slug":"upwork-feed-results-did-not-include-any-job-with-a","errorCode":null,"errorMessage":"Upwork feed results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows.","messagePattern":"Upwork feed results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/upwork/feed.js","lineNumber":105,"sourceCode":"        }\n        if (!payload?.ready) {\n            throw new CommandExecutionError(`Upwork feed state (window.__NUXT__.state.${stateKey}) was not present within 15s`, 'The page may not have finished hydrating, or the SSR state shape may have changed.');\n        }\n        if (!isPlainObject(payload)) {\n            throw new CommandExecutionError('Upwork feed returned an unexpected Browser Bridge payload shape');\n        }\n        if (!payload.jobsPresent || !Array.isArray(payload.jobs)) {\n            throw new CommandExecutionError(`Upwork feed state had an unexpected jobs shape; expected window.__NUXT__.state.${stateKey}.jobs to be an array.`);\n        }\n\n        const jobs = payload.jobs;\n        if (jobs.length === 0) {\n            throw new EmptyResultError(`upwork feed ${tab}`, `Upwork ${tab} feed is empty for the current account`);\n        }\n\n        const rows = jobsToListRows(jobs, { limit });\n        if (rows.length === 0) {\n            throw new CommandExecutionError('Upwork feed results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows.');\n        }\n        return rows;\n    },\n});\n","sourceCodeStart":87,"sourceCodeEnd":110,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/upwork/feed.js#L87-L110","documentation":"The feed maps raw job entries to list rows via jobsToListRows, keeping only jobs that carry a valid ciphertext id so each row can be opened again with `upwork detail`. If the filtered result is empty even though the raw jobs array was non-empty, this CommandExecutionError is thrown: none of the feed entries had a usable ciphertext, so the CLI refuses to emit rows that cannot round-trip to detail.","triggerScenarios":"Running `upwork feed` when every job object in the feed state lacks the expected ciphertext field (or it's empty after trim/normalization) — e.g. an Upwork schema change renaming the id field, job entries being placeholder/promo cards without ids, or jobsToListRows' normalization no longer matching the id key Upwork uses.","commonSituations":"Upwork redesign changing the job id property name in __NUXT__ state; feed entries injected by experiments or ads that have no ciphertext; a stale CLI whose jobsToListRows expects an older field name; partially hydrated state where job ids load late.","solutions":["Retry after a short wait — if ids hydrate late, a re-run may pick up fully populated entries.","Inspect one entry of window.__NUXT__.state.feedBestMatch.jobs in DevTools to find where the ciphertext now lives, and update jobsToListRows (or the CLI package) accordingly.","Update @jackwener/opencli to the latest version that tracks the current Upwork feed schema.","As a workaround, fetch jobs via `upwork search`, whose rows may still carry valid ciphertext ids."],"exampleFix":"// before\nconst rows = jobsToListRows(jobs, { limit });\n// after — diagnose which field now holds the id\nconst sample = jobs[0] || {};\nconst idKey = Object.keys(sample).find(k => /^~0[12]/.test(String(sample[k] || '')));\nif (!idKey) throw new CommandExecutionError('No ciphertext-like field in feed job: ' + JSON.stringify(Object.keys(sample)));\nconst rows = jobsToListRows(jobs, { limit, idKey });","handlingStrategy":"validation","validationCode":"// verify ids exist in feed data before relying on round-trip\nconst res = await upwork.feed();\nconst allHaveIds = res.rows.every(r => /^~0[12]/.test(r.id));\nif (!allHaveIds) console.warn('Feed rows missing ciphertext ids; detail round-trip will fail.');","typeGuard":"function hasCiphertextId(job) {\n  return job != null\n    && typeof job.ciphertext === 'string'\n    && /^~0[12]/.test(job.ciphertext);\n}","tryCatchPattern":"try {\n  const rows = await upwork.feed();\n} catch (e) {\n  if (/valid ciphertext id/.test(e.message)) {\n    // schema drift: inspect the raw jobs array for the new id field, or use `upwork search` rows\n    return fallbackToSearchRows();\n  }\n  throw e;\n}","preventionTips":["Keep the CLI current — this error almost always means Upwork renamed/moved the id field.","Sanity-check a sample feed entry in DevTools after any Upwork UI update.","Maintain a fallback data path (search results) that still carries valid ciphertext ids."],"tags":["upwork","missing-identifier","schema-validation-failed","feed"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}