jackwener/OpenCLI · error · CommandExecutionError

Upwork search returned an unexpected Browser Bridge payload

Error message

Upwork search returned an unexpected Browser Bridge payload shape

What it means

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.

Source

Thrown at clis/upwork/search.js:97

                    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.');
        }
        return rows;
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the CLI and the Browser Bridge script/install to matching versions.
  2. Re-run the command; transient bridge serialization glitches usually don't recur.
  3. Check the bridge transport logs for serialization errors and fix the underlying transport.
  4. If you modified the bridge payload shape, restore the contract: an object with ready, jobsPresent, jobs, onLogin, challenge fields.

Example fix

// before
return; // bridge script returns undefined on some path
// after
return { ready: !!state, jobsPresent: Array.isArray(jobs), jobs: jobs || [], onLogin: !!onLogin, challenge: !!challenge };
Defensive patterns

Strategy: type-guard

Validate before calling

// validate the payload contract before consuming it
function payloadLooksValid(p) {
  return p !== null && typeof p === 'object' && !Array.isArray(p) &&
    'ready' in p && 'jobs' in p;
}

Type guard

function isPlainObject(v) {
  if (v === null || typeof v !== 'object') return false;
  const proto = Object.getPrototypeOf(v);
  return proto === Object.prototype || proto === null;
}

Try / catch

try {
  rows = await cli.search(query);
} catch (e) {
  if (String(e.message).includes('unexpected Browser Bridge payload shape')) {
    await restartBrowserBridge(); // version-skew/serialization glitch recovery
    rows = await cli.search(query);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/c1067cf5e0fec37f. Report an issue: GitHub.