{"record":{"id":"15db56d92e27fede","repo":"jackwener/OpenCLI","slug":"label-must-contain-min-max-min-min","errorCode":null,"errorMessage":"${label} must contain ${min === max ? min : `${min}-${max}`} comma-separated labels","messagePattern":"(.+?) must contain (.+?)-(.+?)`\\} comma-separated labels","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"warning","filePath":"clis/geogebra/utils.js","lineNumber":36,"sourceCode":"  return value;\n}\n\nfunction isPlainObject(value) {\n  return value && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function normalizeLabel(value, label = 'label') {\n  const normalized = String(value ?? '').trim();\n  if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(normalized)) {\n    throw new ArgumentError(`${label} must be an ASCII GeoGebra label like A, B1, or poly_1`);\n  }\n  return normalized;\n}\n\nexport function normalizeLabelList(value, label, min, max = Infinity) {\n  const parts = String(value ?? '').split(',').map(s => s.trim()).filter(Boolean);\n  if (parts.length < min || parts.length > max) {\n    throw new ArgumentError(`${label} must contain ${min === max ? min : `${min}-${max}`} comma-separated labels`);\n  }\n  return parts.map((part, idx) => normalizeLabel(part, `${label}[${idx + 1}]`));\n}\n\nexport function normalizeNumber(value, label, { defaultValue, positive = false } = {}) {\n  const raw = value == null || value === '' ? defaultValue : value;\n  const number = Number(raw);\n  if (!Number.isFinite(number) || (positive && number <= 0)) {\n    throw new ArgumentError(`${label} must be a ${positive ? 'positive ' : ''}finite number`);\n  }\n  return number;\n}\n\nexport function normalizeCoords(value) {\n  const parts = String(value ?? '').split(',').map(s => s.trim());\n  if (parts.length !== 2) {\n    throw new ArgumentError('coords must be in \"x,y\" format (e.g. \"1,2\")');\n  }","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/geogebra/utils.js#L18-L54","documentation":"An ArgumentError from normalizeLabelList: the comma-separated label list had fewer than min or more than max entries. Each entry is then individually validated by normalizeLabel (which reports label[N] on failure). Used e.g. by triangle helpers requiring exactly 3 points.","triggerScenarios":"`--points A,B` when 3 labels are required (too few); `--points A,B,C,D` when max is 3 (too many); passing a single value where a list is required; extra commas producing empty entries are filtered, so 'A,B,' still counts as 2.","commonSituations":"Forgetting the third vertex of a triangle; pasting a space-separated list instead of comma-separated; reusing a two-point argument shape for a three-point command.","solutions":["Supply the required count shown in the message (e.g. min-max range) as comma-separated labels","Use commas, not spaces: --points A,B,C","Remove extra labels if over the maximum","Fix individual label syntax per the follow-up label[N] error if one appears"],"exampleFix":"// before\nopencli geogebra triangle --points A,B\n// after\nopencli geogebra triangle --points A,B,C","handlingStrategy":"validation","validationCode":"const LABEL_RE = /^[A-Za-z][A-Za-z0-9_]*$/;\nconst parts = String(points ?? '').split(',').map(s => s.trim()).filter(Boolean);\nif (parts.length !== 3) throw new Error(`Expected 3 comma-separated labels, got ${parts.length}`);\nif (!parts.every(p => LABEL_RE.test(p))) throw new Error('Each label must match /^[A-Za-z][A-Za-z0-9_]*$/');","typeGuard":"const isValidLabelList = (v, min, max = Infinity) => {\n  const parts = String(v ?? '').split(',').map(s => s.trim()).filter(Boolean);\n  return parts.length >= min && parts.length <= max\n    && parts.every(p => /^[A-Za-z][A-Za-z0-9_]*$/.test(p));\n};","tryCatchPattern":"try {\n  await run('geogebra', 'triangle', '--points', points);\n} catch (err) {\n  if (/must contain .* comma-separated labels/.test(err.message)) {\n    points = normalizeToList(points); // pad/trim to required count\n    return run('geogebra', 'triangle', '--points', points);\n  }\n  throw err;\n}","preventionTips":["Always use comma separation, never spaces, for label lists","Count entries before invoking: triangle helpers typically need exactly 3","Validate each element against the label regex to avoid a follow-up label[N] error"],"tags":["geogebra","label-validation","argument-validation"],"backgroundTag":"invalid-geogebra-label-list","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}