{"record":{"id":"df4e7e3f2f527a8a","repo":"jackwener/OpenCLI","slug":"label-must-be-max-df4e7e","errorCode":null,"errorMessage":"${label} must be <= ${max}","messagePattern":"(.+?) must be <= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":56,"sourceCode":"    return payload.data;\n  }\n  return payload;\n}\n\nexport function normalizeBoolean(value, fallback = false) {\n  if (typeof value === 'boolean') return value;\n  if (value == null || value === '') return fallback;\n  const normalized = String(value).trim().toLowerCase();\n  return ['true', '1', 'yes', 'on'].includes(normalized);\n}\n\nexport function normalizePositiveInt(value, fallback, max, label) {\n  const parsed = value == null || value === '' ? fallback : Number(value);\n  if (!Number.isInteger(parsed) || parsed < 1) {\n    throw new ArgumentError(`${label} must be a positive integer`);\n  }\n  if (parsed > max) {\n    throw new ArgumentError(`${label} must be <= ${max}`);\n  }\n  return parsed;\n}\n\nexport function parseJobId(value) {\n  const raw = String(value ?? '').trim();\n  if (UUID_RE.test(raw)) return raw.toLowerCase();\n  try {\n    const parsed = new URL(raw);\n    const match = parsed.pathname.match(/^\\/jobs\\/([0-9a-f-]{36})\\/?$/i);\n    if (parsed.protocol === 'https:' && parsed.hostname === MIDJOURNEY_DOMAIN && match && UUID_RE.test(match[1])) {\n      return match[1].toLowerCase();\n    }\n  } catch {}\n  throw new ArgumentError(\n    'job-id must be a Midjourney UUID or https://www.midjourney.com/jobs/<uuid> URL',\n    'Example: opencli midjourney status d5664250-5f1f-4cd0-9637-2ce0153dd30a',\n  );","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L38-L74","documentation":"normalizePositiveInt validates that a CLI option value (e.g. --timeout, --limit) is a positive integer and does not exceed an upper bound. When the parsed value exceeds the `max` argument, it throws ArgumentError with \"${label} must be <= ${max}\". This guards API calls against values the Midjourney service would reject.","triggerScenarios":"Calling any midjourney subcommand that resolves `timeout` or `limit` options with a value that parses to a valid positive integer but is greater than the configured max for that option (e.g. --limit 1000 when max is 100).","commonSituations":"Users copying limits from other tools, misremembering the max for a command, script variables containing oversized defaults, or config files with stale values after the CLI tightened its bounds.","solutions":["Check the specific max shown in the error message and lower the option value to that or below","Run the command's help (opencli midjourney --help) to confirm the accepted range for --timeout/--limit","Fix the value in your config file or script where the oversized default is set","If you genuinely need a higher value, split the work into multiple calls within the allowed range"],"exampleFix":"// before\nopencli midjourney list --limit 500\n// after\nopencli midjourney list --limit 100","handlingStrategy":"validation","validationCode":"function isValidPositiveInt(value, max) {\n  const n = value == null || value === '' ? NaN : Number(value);\n  return Number.isInteger(n) && n >= 1 && n <= max;\n}\nif (!isValidPositiveInt(opts.limit, 100)) throw new Error('--limit must be <= 100');","typeGuard":"function isPositiveIntWithinMax(v, max) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= max;\n}","tryCatchPattern":"try {\n  runCommand(opts);\n} catch (err) {\n  if (err.name === 'ArgumentError' && /must be <=/.test(err.message)) {\n    console.error(`Invalid option value: ${err.message}`);\n    process.exitCode = 2;\n  } else throw err;\n}","preventionTips":["Read the help text for --timeout/--limit maxima before scripting","Clamp values in scripts: Math.min(Number(raw), MAX)","Never copy limit values from other tools' docs","Keep bounds in one shared constant if you wrap the CLI"],"tags":["cli","argument-validation","midjourney"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}