jackwener/OpenCLI · error · CommandExecutionError

Upwork detail returned an unexpected Browser Bridge payload

Error message

Upwork detail returned an unexpected Browser Bridge payload shape

What it means

After the login/challenge checks, the command validates that the Browser Bridge payload is a plain object via isPlainObject. If the evaluate returned null, an array, a string, or otherwise non-object data, it throws CommandExecutionError reporting the unexpected payload shape, preventing downstream property access on garbage.

Source

Thrown at clis/upwork/detail.js:89

                    onLogin,
                    challenge,
                    job: s.job ? JSON.parse(JSON.stringify(s.job)) : null,
                    buyer: s.buyer ? JSON.parse(JSON.stringify(s.buyer)) : null,
                };
            })()`));
        }
        catch (e) {
            throw new CommandExecutionError(`Failed to read Upwork job-detail store: ${e?.message ?? e}`, 'The Vuex store 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 (!isPlainObject(payload)) {
            throw new CommandExecutionError('Upwork detail returned an unexpected Browser Bridge payload shape');
        }
        if (!payload?.ready || !payload.job) {
            throw new EmptyResultError('upwork detail', `No Upwork job posting found for id "${id}" (may be closed, expired, or private)`);
        }
        if (!isPlainObject(payload.job)) {
            throw new CommandExecutionError('Upwork job-detail store had an unexpected job shape; expected an object.');
        }

        const job = payload.job;
        const returnedCiphertext = String(job?.ciphertext ?? '').trim();
        if (returnedCiphertext && returnedCiphertext !== id) {
            throw new CommandExecutionError(`Upwork job-detail store returned ciphertext "${returnedCiphertext}" while reading "${id}".`);
        }
        const buyer = payload.buyer || {};
        const stats = buyer?.stats || {};
        const location = buyer?.location || {};
        const category = job?.category?.name || '';
        const skills = formatSkills(job);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with the Upwork job page fully loaded and idle (no pending navigation).
  2. Update the library — mismatched Browser Bridge/injection versions are a frequent cause of shape drift.
  3. Open the job page manually in the connected browser to confirm it renders normally before running the command.
  4. If reproducible on a healthy page, report/inspect: Upwork may have changed its store structure and the extractor needs updating.
  5. Restart the browser bridge connection to rule out stale sessions returning empty results.
Defensive patterns

Strategy: type-guard

Validate before calling

await page.goto(jobUrl, { waitUntil: 'networkidle' });
if (!page.url().includes('upwork.com')) throw new Error('Navigation left Upwork; payload shape cannot be trusted');

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 {
  const detail = await fetchUpworkJobDetail(id);
} catch (e) {
  if (e instanceof CommandExecutionError && /unexpected Browser Bridge payload shape/.test(e.message)) {
    await page.waitForNetworkIdle();
    return fetchUpworkJobDetail(id); // retry once after the page settles
  }
  throw e;
}

Prevention

When it happens

Trigger: The in-page extraction IIFE returns something other than a plain object — evaluate cancelled mid-navigation, script exception produced undefined, a Browser Bridge serialization mismatch, or page context returned a primitive.

Common situations: Page navigated/reloaded during evaluate so the result is undefined/null; a version mismatch between CLI extraction script and the injected bridge; Upwork page erroring before the store reader builds its result object; extensions interfering with page scripts.

Related errors


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