{"record":{"id":"f62226c421bd9aef","repo":"jackwener/OpenCLI","slug":"query-is-required","errorCode":null,"errorMessage":"query is required","messagePattern":"query is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/hltv/search.js","lineNumber":24,"sourceCode":"\ncli({\n  site: 'hltv',\n  name: 'search',\n  description: 'Search HLTV players, teams, events, and articles',\n  access: 'read',\n  example: 'opencli hltv search niko --limit 10 -f json',\n  domain: 'www.hltv.org',\n  strategy: Strategy.UI,\n  browser: true,\n  navigateBefore: false,\n  args: [\n    { name: 'query', type: 'string', positional: true, required: true, help: 'Search keyword, e.g. niko' },\n    { name: 'limit', type: 'int', default: 10, help: 'Maximum rows per result type (max 50)' },\n  ],\n  columns: ['rank', 'type', 'id', 'name', 'title', 'date', 'author', 'url'],\n  func: async (page, args) => {\n    const query = String(args.query ?? '').trim();\n    if (!query) throw new ArgumentError('query is required');\n    const limit = normalizeLimit(args.limit, 10, 50);\n    const url = new URL('/search', BASE);\n    url.searchParams.set('query', query);\n\n    await gotoAndWait(page, url, 'table', 'hltv search page');\n\n    const rows = await page.evaluate((payload) => {\n      const clean = (value) => String(value ?? '').replace(/\\s+/g, ' ').trim();\n      const absolutize = (value) => (value ? new URL(value, payload.base).toString() : null);\n      const extractId = (value, kind) => {\n        if (!value) return null;\n        const path = new URL(value, payload.base).pathname;\n        const patterns = {\n          player: /^\\/player\\/(\\d+)\\//,\n          team: /^\\/team\\/(\\d+)\\//,\n          event: /^\\/events\\/(\\d+)\\//,\n          article: /^\\/news\\/(\\d+)\\//,\n        };","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hltv/search.js#L6-L42","documentation":"The hltv search command requires a non-empty positional 'query'. After trimming, an empty/missing query throws this ArgumentError before any navigation happens. It is an input-validation error, not a scrape failure.","triggerScenarios":"Invoking the search command without the positional query, or with query='' or whitespace-only; programmatically calling with args.query undefined or null.","commonSituations":"Script builds args dynamically and query ends up undefined; CLI call missing the positional argument; user pastes only spaces; wiring bug drops the query field from the args object.","solutions":["Pass a non-empty query string, e.g. niko","Trim and check the query before invoking the command","Ensure the args object actually contains the query key","Show CLI usage/help when the positional argument is absent"],"exampleFix":"// before\nawait run('search', { query: userInput, limit: 10 }); // userInput may be ''\n// after\nconst query = String(userInput ?? '').trim();\nif (!query) throw new Error('search query must be non-empty');\nawait run('search', { query, limit: 10 });","handlingStrategy":"validation","validationCode":"const query = String(args.query ?? '').trim();\nif (!query) throw new Error('query is required before calling search');","typeGuard":"function hasQuery(args) { return typeof args.query === 'string' && args.query.trim().length > 0; }","tryCatchPattern":"try {\n  await searchCommand(page, args);\n} catch (err) {\n  if (err instanceof ArgumentError && /query is required/.test(err.message)) return printUsage();\n  throw err;\n}","preventionTips":["Always pass the positional query explicitly","Trim user input and reject empty strings at the CLI boundary","Add a usage/help message when required args are missing","Never build args objects dynamically without checking required keys"],"tags":["argument-error","validation","input"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}