{"record":{"id":"87b49b020d3e83ca","repo":"heygen-com/hyperframes","slug":"grade-entry-index-1-must-be-an-object-with-la","errorCode":null,"errorMessage":"Grade entry ${index + 1} must be an object with label and grading","messagePattern":"Grade entry (.+?) must be an object with label and grading","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/grade-compare.ts","lineNumber":226,"sourceCode":"export function parseGradesFile(filePath: string): GradeCompareCell[] {\n  if (!existsSync(filePath)) {\n    throw new Error(`Grades file not found: ${filePath}`);\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n  } catch (err) {\n    throw new Error(`Could not parse grades JSON: ${normalizeErrorMessage(err)}`);\n  }\n\n  if (!Array.isArray(parsed)) {\n    throw new Error(\"Grades file must be a JSON array of { label, grading } objects\");\n  }\n\n  return parsed.map((entry, index) => {\n    if (!isRecord(entry)) {\n      throw new Error(`Grade entry ${index + 1} must be an object with label and grading`);\n    }\n    const label = entry.label;\n    if (typeof label !== \"string\" || !label.trim()) {\n      throw new Error(`Grade entry ${index + 1} must have a non-empty string label`);\n    }\n    if (!hasOwn(entry, \"grading\")) {\n      throw new Error(`Grade entry \"${label}\" must include a grading value`);\n    }\n    return validateCell(label, entry.grading);\n  });\n}\n\nexport function resolveLutCells(luts: string): GradeCompareCell[] {\n  const paths = luts\n    .split(\",\")\n    .map((part) => part.trim())\n    .filter(Boolean);\n  if (paths.length === 0) {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/grade-compare.ts#L208-L244","documentation":"Thrown by parseGradesFile() while mapping entries: each entry must pass isRecord (a non-null, non-array object). The index in the message is 1-based (index + 1). A null, primitive, or array element is rejected; only plain objects with label + grading are accepted.","triggerScenarios":"An entry that is null; a string; a number; or an array (e.g. [\"warm\", {}] instead of [{ label, grading }]).","commonSituations":"A malformed comma turning two entries into one array; a placeholder null left in the list; exporting a list of names instead of objects.","solutions":["Make every array element a plain object with label and grading keys","Remove null/primitive placeholders","If a nested array appears, flatten it into individual grade objects"],"exampleFix":"// before (entry is an array, not an object)\n[\n  [\"warm\", {}]\n]\n// after\n[\n  { \"label\": \"warm\", \"grading\": {} }\n]","handlingStrategy":"type-guard","validationCode":"function isRecord(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\nentries.forEach((entry, i) => {\n  if (!isRecord(entry)) throw new Error(`entry ${i + 1} must be an object`);\n});","typeGuard":"function isGradeRecord(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":null,"preventionTips":["Ensure every array element is a plain object","Remove null/primitive placeholders before running","Flatten accidental nested arrays into individual objects"],"tags":["grade-compare","json","type-guard","validation"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}