{"record":{"id":"62ed6917161f1509","repo":"heygen-com/hyperframes","slug":"color-grading-requires-an-img-or-video-select","errorCode":null,"errorMessage":"Color grading requires an <img> or <video>; selector matched <${tag}>","messagePattern":"Color grading requires an <img> or <video>; selector matched <(.+?)>","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/media-treatment.ts","lineNumber":441,"sourceCode":"    matches = queryIncludingTemplates(document, selector);\n  } catch {\n    throw new Error(`Invalid selector: ${selector}`);\n  }\n  if (matches.length === 0) throw new Error(`Selector did not match: ${selector}`);\n  if (selectorIndex === undefined && matches.length > 1) {\n    throw new Error(\n      `Selector matched ${matches.length} elements; use a unique selector or --selector-index`,\n    );\n  }\n\n  const resolvedIndex = selectorIndex ?? 0;\n  const element = matches[resolvedIndex];\n  if (!element) {\n    throw new Error(`--selector-index ${resolvedIndex} is outside ${matches.length} matches`);\n  }\n  const tag = element.tagName.toLowerCase();\n  if (tag !== \"img\" && tag !== \"video\") {\n    throw new Error(`Color grading requires an <img> or <video>; selector matched <${tag}>`);\n  }\n  return { element, selectorIndex: resolvedIndex, tag };\n}\n\nexport function applyMediaTreatmentToHtml(\n  source: string,\n  options: ApplyMediaTreatmentOptions,\n): ApplyMediaTreatmentResult {\n  const { element, selectorIndex, tag } = selectMediaElement(\n    source,\n    options.selector,\n    options.selectorIndex,\n  );\n  const before = parseStoredGrading(element.getAttribute(HF_COLOR_GRADING_ATTR));\n\n  const value = options.clear ? null : serializeGradingPatch(before, options.grading);\n\n  const changed = element.getAttribute(HF_COLOR_GRADING_ATTR) !== value;","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/media-treatment.ts#L423-L459","documentation":"Thrown by selectMediaElement() in packages/cli/src/commands/media-treatment.ts:440. After resolving a single element, it lowercases tagName and requires 'img' or 'video' — color grading only applies to media. Any other tag (div, picture, source, a, span, etc.) throws, naming the matched tag.","triggerScenarios":"A selector that resolves to a non-media element: a wrapper div around an image, a <picture> element, a <source> inside a <video>, an <a> wrapping an image, etc.","commonSituations":"Targeting '.hero' which is the wrapper div, not the img inside; targeting <picture> instead of its child <img>; targeting <source> instead of the parent <video>.","solutions":["Make the selector resolve to the actual <img> or <video> element (e.g. '#hero img' instead of '#hero').","For <picture>, target the inner <img>; for <video> with <source> children, target the <video> itself.","Inspect the matched tag in the error message and adjust the selector accordingly."],"exampleFix":"<!-- DOM: <div id=\"hero\"><img src=\"hero.png\"></div> -->\n# before -- matched <div>\nhyperframes media-treatment --selector '#hero' --grading '{...}' --apply\n# after -- target the img\nhyperframes media-treatment --selector '#hero img' --grading '{...}' --apply","handlingStrategy":"type-guard","validationCode":"import { parseHTML } from 'linkedom';\n\nfunction selectorTargetsMedia(selector: string, source: string): boolean {\n  const { document } = parseHTML(source);\n  const el = document.querySelector(selector);\n  if (!el) return false;\n  const tag = el.tagName.toLowerCase();\n  return tag === 'img' || tag === 'video';\n}","typeGuard":"function isMediaTag(tag: string): tag is 'img' | 'video' {\n  return tag === 'img' || tag === 'video';\n}","tryCatchPattern":"try {\n  selectMediaElement(source, selector);\n} catch (error) {\n  if (/Color grading requires an <img> or <video>/.test(String(error))) {\n    // target the inner img/video instead of the wrapper\n    selectMediaElement(source, `${selector} img, ${selector} video`);\n  } else throw error;\n}","preventionTips":["Target the actual <img>/<video>, not a wrapper, <picture>, or <source>.","For <picture>, select the child <img>; for <video>, select the <video> not <source>.","Inspect the matched tag name reported in the error to adjust."],"tags":["css","media","validation","media-treatment"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}