{"record":{"id":"6116393377be84cb","repo":"jackwener/OpenCLI","slug":"facebook-search-requires-a-non-empty-query","errorCode":null,"errorMessage":"facebook search requires a non-empty query","messagePattern":"facebook search requires a non-empty query","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/facebook/search.js","lineNumber":17,"sourceCode":"import { ArgumentError, AuthRequiredError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\nimport { cli, Strategy } from '@jackwener/opencli/registry';\n\nconst FACEBOOK_HOME = 'https://www.facebook.com';\nconst MAX_LIMIT = 50;\n\nfunction requireLimit(value) {\n  const n = Number(value);\n  if (!Number.isInteger(n) || n < 1 || n > MAX_LIMIT) {\n    throw new ArgumentError(`facebook search --limit must be an integer between 1 and ${MAX_LIMIT}`);\n  }\n  return n;\n}\n\nfunction requireQuery(value) {\n  const q = String(value ?? '').trim();\n  if (!q) throw new ArgumentError('facebook search requires a non-empty query');\n  return q;\n}\n\nfunction unwrapBrowserResult(value) {\n  if (value && typeof value === 'object' && 'data' in value) return value.data;\n  return value;\n}\n\n// Modern facebook.com /search/top renders results inside [role=\"feed\"] as\n// entity/content links (people, pages, groups, posts) — [role=\"article\"] /\n// [role=\"listitem\"] no longer wrap them — and FB seeds scrambled hidden-char\n// decoy links back to /search/top. Collect anchors inside the feed, keep only\n// real entity/content hrefs, and drop the decoys plus obfuscated text. See #2090.\nfunction buildSearchExtractScript(limit) {\n  return `(() => {\n    const limit = ${limit};\n\n    function clean(value) {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/facebook/search.js#L1-L35","documentation":"ArgumentError thrown by requireQuery when the search query is missing, empty, or whitespace-only. requireQuery trims String(value ?? '') and rejects falsy results before the search runs. It is a local input validation guard raised before any browser navigation.","triggerScenarios":"Running `facebook search` with no --query argument, an empty string (--query \"\"), or a value consisting only of whitespace.","commonSituations":"Scripting where the query variable is empty or null; shell quoting issues dropping the argument; user forgetting the required flag.","solutions":["Supply a non-empty query, e.g. facebook search --query \"openai\"","Trim and check the value before invoking: if (!q?.trim()) return early","Fix shell quoting so the argument is actually passed"],"exampleFix":"// before\nconst q = process.env.QUERY; // may be undefined\nawait cli.search({ query: q });\n// after\nconst q = (process.env.QUERY ?? '').trim();\nif (!q) throw new Error('QUERY is required');\nawait cli.search({ query: q });","handlingStrategy":"validation","validationCode":"const q = (rawQuery ?? '').trim();\nif (!q) throw new Error('A non-empty search query is required');\nawait cli.search({ query: q });","typeGuard":"function hasQuery(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await cli.search({ query });\n} catch (err) {\n  if (/requires a non-empty query/.test(err.message)) {\n    console.error('Usage: facebook search --query \"<terms>\"');\n    process.exitCode = 2;\n    return;\n  }\n  throw err;\n}","preventionTips":["Trim and check user-supplied queries before invoking","Beware shell quoting: \"\" passes an empty string","Default or prompt for a query in scripts instead of passing undefined"],"tags":["validation","argument-error","cli-input"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}