{"record":{"id":"e5a8d7f629330dae","repo":"heygen-com/hyperframes","slug":"selected-media-has-no-analyzable-src","errorCode":null,"errorMessage":"Selected media has no analyzable src","messagePattern":"Selected media has no analyzable src","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/media-treatment.ts","lineNumber":485,"sourceCode":"  return { html: patched.html, changed: true, tag, value, before, after };\n}\n\nfunction parseSelectorIndex(raw: string | undefined): number | undefined {\n  if (raw === undefined) return undefined;\n  const value = Number(raw);\n  if (!Number.isInteger(value) || value < 0) {\n    throw new Error(\"--selector-index must be a non-negative integer\");\n  }\n  return value;\n}\n\nfunction mediaSourceForElement(element: Element): string {\n  const src =\n    element.getAttribute(\"src\") ??\n    (element.tagName.toLowerCase() === \"video\"\n      ? element.querySelector(\"source\")?.getAttribute(\"src\")\n      : null);\n  if (!src) throw new Error(\"Selected media has no analyzable src\");\n  return src;\n}\n\nexport function resolveMediaTreatmentSource(\n  projectDir: string,\n  compositionFile: string,\n  source: string,\n): string {\n  const sourceUrl = source.trim();\n  if (!sourceUrl) throw new Error(\"Selected media has no analyzable local src\");\n  if (isRemoteOrInlineUrl(sourceUrl)) {\n    throw new Error(\n      \"Media analysis requires a local project asset; freeze remote media with media-use first\",\n    );\n  }\n  const cleanSource = cleanAssetUrl(sourceUrl);\n  if (!cleanSource) throw new Error(\"Selected media has no analyzable local src\");\n  const projectRelative = cleanSource.startsWith(\"/\")","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/media-treatment.ts#L467-L503","documentation":"Thrown by mediaSourceForElement() in packages/cli/src/commands/media-treatment.ts:479. It reads element.getAttribute('src'), and for <video> also falls back to the first <source> child's src. If neither yields a truthy value, it throws — analysis requires a concrete media URL to probe with ffprobe.","triggerScenarios":"An <img> with no src attribute; a <video> with neither a src attribute nor a <source> child with src; an element whose src was intentionally blank.","commonSituations":"Lazy-loaded images using data-src instead of src; <video> whose sources are set by client-side JS; <picture> where the <img> has no src; placeholder elements; src attribute empty.","solutions":["Ensure the matched <img>/<video> has a real src attribute (or a <source> child with src for video) in static HTML.","For lazy-loaded media, materialize the src (copy data-src to src) before analysis.","If the media is remote, freeze it locally with `hyperframes media-use` first so a local src exists."],"exampleFix":"<!-- before -- no src to analyze -->\n<img id=\"hero\" data-src=\"hero.png\">\n<!-- after -->\n<img id=\"hero\" src=\"hero.png\">","handlingStrategy":"type-guard","validationCode":"function hasAnalyzableSrc(el: Element): boolean {\n  if (el.getAttribute('src')) return true;\n  if (el.tagName.toLowerCase() === 'video') {\n    return Boolean(el.querySelector('source')?.getAttribute('src'));\n  }\n  return false;\n}","typeGuard":"function hasAnalyzableSrc(el: Element): boolean {\n  if (el.getAttribute('src')) return true;\n  if (el.tagName.toLowerCase() === 'video') {\n    return Boolean(el.querySelector('source')?.getAttribute('src'));\n  }\n  return false;\n}","tryCatchPattern":"try {\n  mediaSourceForElement(element);\n} catch (error) {\n  if (/no analyzable src/.test(String(error))) {\n    // materialize data-src into src, or skip analysis for this element\n    throw new Error('Element has no src; materialize data-src or set a real src first.');\n  }\n  throw error;\n}","preventionTips":["Author <img>/<video> with a real src attribute in static HTML, not just data-src.","For lazy-loaded media, copy data-src to src before analysis.","Freeze remote media locally with `hyperframes media-use` before analyzing."],"tags":["media","validation","media-treatment"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}