jackwener/OpenCLI · error · CliError

INVALID_ARGUMENT

INVALID_ARGUMENT

Error message

jobId is required

What it means

The 51job job detail command validates that a jobId argument was supplied; when kwargs.jobId is missing, null, or an empty/whitespace string after trim, it throws CliError('INVALID_ARGUMENT'). This is an input-validation failure thrown synchronously before any navigation or network work.

Source

Thrown at clis/51job/detail.js:35

    description: '51job 职位详情(按 jobId)',
    domain: 'jobs.51job.com',
    strategy: Strategy.COOKIE,
    browser: true,
    navigateBefore: false,
    args: [
        { name: 'jobId', type: 'string', required: true, positional: true, help: '职位 ID(search 返回的 jobId)' },
    ],
    columns: [
        'jobId', 'title', 'salary', 'location', 'workYear', 'degree',
        'category', 'address', 'ageRequirement',
        'description', 'welfare',
        'company', 'companyType', 'companySize', 'companyIndustry',
        'companyUrl', 'url',
    ],
    func: async (page, kwargs) => {
        requirePage(page);
        const jobId = String(kwargs.jobId ?? '').trim();
        if (!jobId) throw new CliError('INVALID_ARGUMENT', 'jobId is required');
        if (!/^\d{6,12}$/.test(jobId)) throw new CliError('INVALID_ARGUMENT', `jobId must be a 6-12 digit number, got "${jobId}"`);

        const url = `${JOBS_ORIGIN}/x/${jobId}.html`;
        await navigateTo(page, url, 2);

        const script = `(() => {
            const sel = s => document.querySelector(s)?.innerText?.trim() || '';
            const all = s => [...document.querySelectorAll(s)].map(e => e.innerText.trim()).filter(Boolean);
            const finalUrl = window.location.href;
            const bodyText = (document.body.innerText || '').slice(0, 400);
            if (/职位已下线|该职位已删除|页面不存在/.test(bodyText)) {
                return { error: 'EXPIRED', bodyText };
            }
            const companyA = document.querySelector('.cname a, .tCompany_sidebar .com_msg a');
            const funcs = all('.bmsg .fp');
            const pick = (prefix) => {
                const row = funcs.find(f => f.startsWith(prefix));
                return row ? row.slice(prefix.length).replace(/^[::\\s\\n]+/, '').trim() : '';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a valid jobId string/number in the call arguments
  2. Check the property name is exactly jobId (not id/jobID)
  3. Guard upstream data: skip or log items without an id before calling detail
  4. If ids come from a search result, ensure the mapping step copies the id field

Example fix

// before
await cli.detail({ id: job.id });
// after
if (!job.jobId) throw new Error('missing jobId for ' + job.title);
await cli.detail({ jobId: job.jobId });
Defensive patterns

Strategy: validation

Validate before calling

const jobId = String(job?.jobId ?? '').trim();
if (!jobId) throw new Error('jobId is required before calling detail');

Type guard

const hasJobId = (j) => j != null && String(j.jobId ?? '').trim() !== '';

Try / catch

try {
  return await cli.detail({ jobId });
} catch (e) {
  if (e.code === 'INVALID_ARGUMENT') { console.warn('skip: missing jobId'); return null; }
  throw e;
}

Prevention

When it happens

Trigger: Calling the detail subcommand without jobId, or with jobId as undefined/null/'' (e.g. String(kwargs.jobId ?? '').trim() yields empty) — thrown at clis/51job/detail.js:35.

Common situations: Programmatic callers piping results where an upstream job item lacked an id; building the call from config where the jobId key is misspelled; passing a variable that is undefined due to a failed destructure.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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