{"record":{"id":"c1067cf5e0fec37f","repo":"jackwener/OpenCLI","slug":"upwork-search-returned-an-unexpected-browser-bridg","errorCode":null,"errorMessage":"Upwork search returned an unexpected Browser Bridge payload shape","messagePattern":"Upwork search returned an unexpected Browser Bridge payload shape","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/upwork/search.js","lineNumber":97,"sourceCode":"                    status: state ? state.status : null,\n                };\n            })()`));\n        }\n        catch (e) {\n            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.');\n        }\n\n        if (payload?.onLogin) {\n            throw new AuthRequiredError('upwork.com', 'Upwork redirected to login. Open https://www.upwork.com in the connected browser and sign in, then retry.');\n        }\n        if (payload?.challenge) {\n            throw new CommandExecutionError('Upwork served a Cloudflare challenge page', 'Open https://www.upwork.com in the connected browser and clear the challenge, then retry.');\n        }\n        if (!payload?.ready) {\n            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.');\n        }\n        if (!isPlainObject(payload)) {\n            throw new CommandExecutionError('Upwork search returned an unexpected Browser Bridge payload shape');\n        }\n        if (!payload.jobsPresent || !Array.isArray(payload.jobs)) {\n            throw new CommandExecutionError('Upwork search state had an unexpected jobs shape; expected window.__NUXT__.state.jobsSearch.jobs to be an array.');\n        }\n\n        const jobs = payload.jobs;\n        if (jobs.length === 0) {\n            throw new EmptyResultError('upwork search', `No Upwork jobs matched \"${query}\"${location ? ` in ${location}` : ''}`);\n        }\n\n        const offset = (pageNum - 1) * perPage;\n        const rows = jobsToListRows(jobs, { offset, limit: perPage });\n        if (rows.length === 0) {\n            throw new CommandExecutionError('Upwork search results did not include any job with a valid ciphertext id; cannot produce round-trippable detail rows.');\n        }\n        return rows;\n    },\n});","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/upwork/search.js#L79-L115","documentation":"A CommandExecutionError thrown when the Browser Bridge payload returned from the page is not a plain object, meaning the bridge's contract (a serializable result object with ready/jobs flags) was violated. This is a defensive shape check on the CLI side, so it usually indicates a bridge or page script malfunction rather than an Upwork problem.","triggerScenarios":"The in-page evaluation returns something other than a plain object - e.g. the bridge returned undefined/null, a serialization failure produced a non-object, or a custom/modified bridge script returned a different structure than the CLI expects.","commonSituations":"Running a mismatched or older Browser Bridge script against a newer CLI (version skew); a bridge transport that fails serialization and returns a degenerate value; tampered or monkey-patched page globals altering the script's return value.","solutions":["Update the CLI and the Browser Bridge script/install to matching versions.","Re-run the command; transient bridge serialization glitches usually don't recur.","Check the bridge transport logs for serialization errors and fix the underlying transport.","If you modified the bridge payload shape, restore the contract: an object with ready, jobsPresent, jobs, onLogin, challenge fields."],"exampleFix":"// before\nreturn; // bridge script returns undefined on some path\n// after\nreturn { ready: !!state, jobsPresent: Array.isArray(jobs), jobs: jobs || [], onLogin: !!onLogin, challenge: !!challenge };","handlingStrategy":"type-guard","validationCode":"// validate the payload contract before consuming it\nfunction payloadLooksValid(p) {\n  return p !== null && typeof p === 'object' && !Array.isArray(p) &&\n    'ready' in p && 'jobs' in p;\n}","typeGuard":"function isPlainObject(v) {\n  if (v === null || typeof v !== 'object') return false;\n  const proto = Object.getPrototypeOf(v);\n  return proto === Object.prototype || proto === null;\n}","tryCatchPattern":"try {\n  rows = await cli.search(query);\n} catch (e) {\n  if (String(e.message).includes('unexpected Browser Bridge payload shape')) {\n    await restartBrowserBridge(); // version-skew/serialization glitch recovery\n    rows = await cli.search(query);\n  } else throw e;\n}","preventionTips":["Keep the CLI and Browser Bridge script versions in sync.","Do not modify the bridge script's return contract (ready/jobsPresent/jobs/onLogin/challenge).","Watch for bridge transport serialization errors in logs.","Re-run once before debugging - many payload-shape glitches are transient."],"tags":["contract-violation","browser-bridge","upwork","payload-shape"],"backgroundTag":"unexpected-payload-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}