{"record":{"id":"606df37147b2d877","repo":"jackwener/OpenCLI","slug":"channel-required-606df3","errorCode":null,"errorMessage":"channel required","messagePattern":"channel required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/slock/channel-files.js","lineNumber":26,"sourceCode":"\ncli({\n  site: SLOCK_SITE,\n  name: 'channel-files',\n  access: 'read',\n  description: 'List files shared in a channel (GET /channels/:id/files)',\n  domain: SLOCK_DOMAIN,\n  strategy: Strategy.COOKIE,\n  browser: true,\n  siteSession: 'persistent',\n  args: [\n    { name: 'channel', positional: true, required: true, help: 'channelId UUID or #name' },\n    { name: 'limit', type: 'int', default: 50, help: 'Max files' },\n    { name: 'server', help: 'Override active server' },\n  ],\n  columns: ['id', 'filename', 'mimeType', 'sizeBytes', 'messageId', 'createdAt'],\n  func: async (page, kwargs) => {\n    const channel = String(kwargs.channel ?? '').trim();\n    if (!channel) throw new ArgumentError('channel required');\n    const limit = parsePositiveInteger(kwargs.limit, '--limit', { defaultValue: 50 });\n    await page.goto(SLOCK_HOME_URL);\n    const snippet = buildChannelScopedSnippet({\n      channelInput: channel,\n      method: 'GET',\n      pathSuffix: '/files',\n      query: `?limit=${limit}`,\n      serverIdOverride: kwargs.server,\n    });\n    const result = await page.evaluate(`(async () => { ${snippet} })()`);\n    const data = dispatchEvaluateResult(result);\n    const files = Array.isArray(data) ? data : (data.files || []);\n    if (!Array.isArray(files)) {\n      throw new CommandExecutionError(`expected files array, got ${typeof files} (contract drift?)`);\n    }\n    return files.map((f) => ({\n      id: f.id ?? '',\n      filename: f.filename ?? '',","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/slock/channel-files.js#L8-L44","documentation":"`channel-files` requires a target channel. The CLI trims the `channel` kwarg and throws ArgumentError('channel required') when it is missing or empty, before navigating or building the fetch snippet.","triggerScenarios":"Calling `slock channel-files` without `--channel`, or with an empty/whitespace-only value.","commonSituations":"Scripting loops where the channel variable is unset for some iterations, forgetting the positional/flag in an alias, or a wrapper script that forwards kwargs incorrectly.","solutions":["Pass the channel: `slock channel-files --channel '#ops'` or the channelId UUID","Verify the variable feeding --channel is non-empty before invoking","Check the command's help (`slock channel-files --help`) for the expected flag"],"exampleFix":"// before\n$ slock channel-files --limit 10\nError: channel required\n// after\n$ slock channel-files --channel '#ops' --limit 10","handlingStrategy":"validation","validationCode":"const channel = String(input.channel ?? '').trim();\nif (!channel) throw new Error('channel must be provided (#name or channelId UUID)');","typeGuard":"const hasChannel = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try {\n  await run(['slock', 'channel-files', '--channel', channel]);\n} catch (e) {\n  if (e instanceof ArgumentError && e.message === 'channel required') {\n    console.error('Pass --channel <#name|uuid>; the value was empty.');\n  } else throw e;\n}","preventionTips":["Make --channel explicit in every invocation","Skip empty entries when looping over channel lists","Wrap the CLI in a helper that asserts required args"],"tags":["argument-error","cli","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}