{"record":{"id":"ef9ec3eaf3016ec8","repo":"heygen-com/hyperframes","slug":"could-not-parse-grading-json-normalizeerrorme","errorCode":null,"errorMessage":"Could not parse --grading JSON: ${normalizeErrorMessage(error)}","messagePattern":"Could not parse --grading JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/media-treatment.ts","lineNumber":526,"sourceCode":"  return asset.resolved;\n}\n\nfunction parseGrading(raw: string | undefined, apply: boolean, clear: boolean): unknown {\n  if (clear) {\n    if (raw !== undefined || apply) {\n      throw new Error(\"Use either --apply with --grading or --clear, not both\");\n    }\n    return undefined;\n  }\n  if (!apply) {\n    if (raw !== undefined) throw new Error(\"--grading requires --apply\");\n    throw new Error(\"Use --apply with --grading <json> or --clear\");\n  }\n  if (raw === undefined) throw new Error(\"--apply requires --grading <json>\");\n  try {\n    return JSON.parse(raw);\n  } catch (error) {\n    throw new Error(`Could not parse --grading JSON: ${normalizeErrorMessage(error)}`);\n  }\n}\n\nfunction mutationVerb(action: \"apply\" | \"clear\", changed: boolean, dryRun: boolean): string {\n  if (dryRun) return `Would ${action}`;\n  if (!changed) return action === \"apply\" ? \"Already applied\" : \"Already clear\";\n  return action === \"apply\" ? \"Applied\" : \"Cleared\";\n}\n\ninterface MediaTreatmentCommandArgs {\n  capabilities?: boolean;\n  capability?: string;\n  all?: boolean;\n  project?: string;\n  file?: string;\n  selector?: string;\n  \"selector-index\"?: string;\n  grading?: string;","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/media-treatment.ts#L508-L544","documentation":"Thrown by parseGrading when JSON.parse(raw) throws on the --grading string. The value must be valid JSON conforming to the HyperFrames color-grading contract. The wrapped normalizeErrorMessage extracts the underlying SyntaxError detail (unexpected token, trailing comma, etc.).","triggerScenarios":"Passing single-quoted JSON (shell-style), trailing commas, unquoted keys, or a preset name string without object wrapping. Example: --grading \"{preset:'warm'}\" fails because keys/values need double quotes.","commonSituations":"Shell quoting issues (single quotes inside double quotes). Hand-written JSON with JS-object shorthand. Copy-pasting from JS source where keys are unquoted. Trailing commas from edited JSON.","solutions":["Use strictly valid JSON: double-quoted keys and string values, no trailing commas","Single-quote the whole argument in the shell and use double quotes inside: --grading '{\"preset\":\"warm\"}'","Validate the JSON with a linter or `echo '<json>' | jq .` before passing it","Discover valid shapes via `hyperframes media-treatment --capability <id> --json`"],"exampleFix":"// before — single quotes inside, invalid JSON\nhyperframes media-treatment --selector '#hero' --grading \"{'preset':'warm'}\" --apply\n// after — valid JSON, shell-single-quoted\nhyperframes media-treatment --selector '#hero' --grading '{\"preset\":\"warm\"}' --apply","handlingStrategy":"try-catch","validationCode":"function tryParseGradingJson(raw: string): unknown {\n  try {\n    return JSON.parse(raw);\n  } catch (e) {\n    throw new Error(`Invalid grading JSON: ${(e as Error).message}. Use double-quoted keys/values.`);\n  }\n}\n// validate before building the CLI command\nconst parsed = tryParseGradingJson(gradingArg);","typeGuard":null,"tryCatchPattern":"try {\n  JSON.parse(gradingRaw);\n} catch (e) {\n  // surface a hint about double quotes / no trailing commas, then re-prompt\n}","preventionTips":["Pipe grading JSON through `jq .` to validate before passing it to the CLI","Always single-quote the argument in the shell and use double quotes inside"],"tags":["media-treatment","cli","json-parse","validation"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}