{"record":{"id":"7b5c598be02171ec","repo":"heygen-com/hyperframes","slug":"invalid-selector-selector","errorCode":null,"errorMessage":"Invalid selector: ${selector}","messagePattern":"Invalid selector: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/media-treatment.ts","lineNumber":425,"sourceCode":"  if (matches.length > 0) return matches;\n  for (const template of root.querySelectorAll(\"template\")) {\n    const nested = queryIncludingTemplates(template, selector);\n    if (nested.length > 0) return nested;\n  }\n  return [];\n}\n\nfunction selectMediaElement(\n  source: string,\n  selector: string,\n  selectorIndex?: number,\n): { element: Element; selectorIndex: number; tag: \"img\" | \"video\" } {\n  const document = parseSourceDocument(source);\n  let matches: Element[];\n  try {\n    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 };","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/media-treatment.ts#L407-L443","documentation":"Thrown by selectMediaElement() in packages/cli/src/commands/media-treatment.ts:415. It wraps queryIncludingTemplates -> querySelectorAll in try/catch; if the underlying DOM (parseHTML/linkedom) throws a DOMException for a malformed selector, the catch rethrows this friendlier message. Note it fires only when the selector is syntactically invalid — a valid selector that matches nothing is a different error.","triggerScenarios":"Passing `--selector` with invalid CSS syntax: unbalanced brackets, unsupported pseudo-class, illegal combinators, stray characters, or unescaped special characters.","commonSituations":"Typo in the selector; copy-paste with hidden characters; selectors using pseudo-classes linkedom doesn't support; ids/classes starting with a digit and not escaped.","solutions":["Test the selector in a browser devtools console against the same HTML; if it throws there, it throws here.","Escape special characters (e.g. '#hero.main' should be '#hero\\\\.main' or use [id='hero.main']).","Simplify the selector to confirm syntax, then add complexity back.","Use --dry-run --json to iterate quickly without writing."],"exampleFix":"# before -- invalid: stray colon / unbalanced\nhyperframes media-treatment --selector 'img[' --apply --grading '{...}'\n# after\nhyperframes media-treatment --selector 'img.hero' --apply --grading '{...}'","handlingStrategy":"validation","validationCode":"import { parseHTML } from 'linkedom';\n\nfunction isValidSelector(selector: string, source: string): boolean {\n  const { document } = parseHTML(source);\n  try {\n    document.querySelectorAll(selector);\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":"function isValidSelectorSyntax(selector: string): boolean {\n  try {\n    document.querySelector(selector);\n    return true;\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  selectMediaElement(source, selector);\n} catch (error) {\n  if (/Invalid selector/.test(String(error))) {\n    // ask the caller for a syntactically valid CSS selector\n    throw new Error(`Selector syntax invalid: ${selector}`);\n  }\n  throw error;\n}","preventionTips":["Test selectors in browser devtools or with linkedom's querySelectorAll before passing them to the CLI.","Escape special characters in ids/classes (use attribute selectors for ids containing dots).","Avoid pseudo-classes linkedom doesn't implement."],"tags":["css","validation","media-treatment"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}