{"record":{"id":"6540de620437835c","repo":"jackwener/OpenCLI","slug":"query-is-required-6540de","errorCode":null,"errorMessage":"query is required","messagePattern":"query is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/search.js","lineNumber":424,"sourceCode":"        { name: 'location', type: 'string', required: false, help: 'Location text such as San Francisco Bay Area' },\n        { name: 'limit', type: 'int', default: 10, help: 'Number of jobs to return (max 100)' },\n        { name: 'start', type: 'int', default: 0, help: 'Result offset for pagination' },\n        { name: 'details', type: 'bool', default: false, help: 'Include full job description and apply URL (slower)' },\n        { name: 'company', type: 'string', required: false, help: 'Comma-separated company names or LinkedIn company IDs' },\n        { name: 'experience-level', type: 'string', required: false, help: 'Comma-separated: internship, entry, associate, mid-senior, director, executive' },\n        { name: 'job-type', type: 'string', required: false, help: 'Comma-separated: full-time, part-time, contract, temporary, volunteer, internship, other' },\n        { name: 'date-posted', type: 'string', required: false, help: 'One of: any, month, week, 24h' },\n        { name: 'remote', type: 'string', required: false, help: 'Comma-separated: on-site, hybrid, remote' },\n    ],\n    columns: ['rank', 'title', 'company', 'location', 'listed', 'salary', 'url'],\n    func: async (page, kwargs) => {\n        const limit = parseIntegerArg(kwargs.limit, '--limit', 10, MIN_LIMIT, MAX_LIMIT);\n        const start = parseIntegerArg(kwargs.start, '--start', 0, MIN_START);\n        const includeDetails = Boolean(kwargs.details);\n        const location = (kwargs.location ?? '').trim();\n        const keywords = String(kwargs.query ?? '').trim();\n        if (!keywords)\n            throw new ArgumentError('query is required');\n        const searchParams = new URLSearchParams({ keywords });\n        if (location)\n            searchParams.set('location', location);\n        await page.goto(`https://www.linkedin.com/jobs/search/?${searchParams.toString()}`);\n        await assertLinkedInAuthenticated(page, 'LinkedIn search');\n        await page.wait({ text: 'Jobs', timeout: 10 });\n        const companyIds = await resolveCompanyIds(page, kwargs.company);\n        const input = {\n            keywords,\n            location,\n            limit,\n            start,\n            companyIds,\n            experienceLevels: mapFilterValues(kwargs['experience-level'], EXPERIENCE_LEVELS, 'experience_level'),\n            jobTypes: mapFilterValues(kwargs['job-type'], JOB_TYPES, 'job_type'),\n            datePostedValues: mapFilterValues(kwargs['date-posted'], DATE_POSTED, 'date_posted'),\n            remoteTypes: mapFilterValues(kwargs.remote, REMOTE_TYPES, 'remote'),\n        };","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/search.js#L406-L442","documentation":"The linkedin search command declares `query` as a required positional argument, and the func re-validates it: after trimming, an empty keywords string throws this ArgumentError. The keywords are mandatory because they become the `keywords:` term of the LinkedIn jobs search query.","triggerScenarios":"Calling `opencli linkedin search` with no positional argument, with an empty string (`--query \"\"` or positional \"\"), or with a value that is only whitespace (e.g. ' '), so `String(kwargs.query ?? '').trim()` yields ''. Also occurs when programmatic callers pass kwargs.query as null/undefined.","commonSituations":"Shell quoting mistakes that drop the argument; scripts interpolating an empty variable (`search \"$Q\"` with Q unset); wrappers forwarding kwargs without mapping the positional; users assuming other filters alone (e.g. --company) can drive a search.","solutions":["Pass a non-empty keywords argument, e.g. `opencli linkedin search \"software engineer\"`.","If the value comes from a variable, check it is non-empty before invoking; quote it in the shell so it is not swallowed.","If you only want to filter without keywords, you still must supply some search text — use a broad term like 'engineer' combined with --company/--location filters."],"exampleFix":"// before (Q empty -> ArgumentError)\nconst q = process.env.QUERY || '';\nawait run(['linkedin', 'search', q]);\n// after\nconst q = (process.env.QUERY || '').trim();\nif (!q) throw new Error('QUERY env var must be a non-empty search string');\nawait run(['linkedin', 'search', q]);","handlingStrategy":"validation","validationCode":"const query = (process.argv[2] || '').trim();\nif (!query) {\n  console.error('Usage: opencli linkedin search <query> [--location ...]');\n  process.exit(1);\n}\nawait run(['linkedin', 'search', query]);","typeGuard":"const hasQuery = (kwargs) =>\n  typeof kwargs?.query === 'string' && kwargs.query.trim().length > 0;","tryCatchPattern":"try {\n  await run(['linkedin', 'search', query]);\n} catch (e) {\n  if (/query is required/.test(e.message)) {\n    console.error('Provide a non-empty search string as the positional argument.');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Quote the positional query in shell scripts so it is never swallowed (`\"$QUERY\"`).","Default empty variables to a sensible search term or fail fast before invoking.","Validate user-supplied input is non-empty after trimming before calling the command.","Remember filters like --company cannot substitute for keywords; always supply search text."],"tags":["linkedin","argument-validation","missing-argument","input-validation"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}