{"record":{"id":"1e3d5538de823b4f","repo":"remotion-dev/remotion","slug":"expected-video-config","errorCode":null,"errorMessage":"Expected video config","messagePattern":"Expected video config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio/src/components/AudioWaveform.tsx","lineNumber":77,"sourceCode":"}> = ({\n\tsrc,\n\theight,\n\tstartFrom,\n\tdurationInFrames,\n\tdisplayOffsetInFrames,\n\tdisplayDurationInFrames,\n\tvisualizationWidth,\n\tvolume,\n\tdoesVolumeChange,\n\tmuted,\n\tplaybackRate,\n\tloopDisplay,\n}) => {\n\tconst [peaks, setPeaks] = useState<Float32Array | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst vidConf = Internals.useUnsafeVideoConfig();\n\tif (vidConf === null) {\n\t\tthrow new Error('Expected video config');\n\t}\n\n\tconst waveformSampleRate = Math.ceil(\n\t\tvidConf.fps * TIMELINE_FRAME_WIDTH_AT_MAX_ZOOM,\n\t);\n\n\tconst waveformCanvas = useRef<HTMLCanvasElement>(null);\n\tconst volumeCanvas = useRef<HTMLCanvasElement>(null);\n\tconst shouldRenderVolumeOverlay =\n\t\tdoesVolumeChange && typeof volume === 'string';\n\tconst parsedVolume = useMemo(() => parseVolume(volume), [volume]);\n\tconst visibleVolume = useMemo((): WaveformVolume => {\n\t\tif (muted) {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn getVisibleWaveformVolume({\n\t\t\tdisplayDurationInFrames,","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/remotion-dev/remotion/blob/a6a7485a9aeb04219510fbe4874f8941486424df/packages/studio/src/components/AudioWaveform.tsx#L59-L95","documentation":"AudioWaveform in Remotion Studio renders an audio waveform on the timeline, and it needs the current video configuration (fps, dimensions, etc.) via Internals.useUnsafeVideoConfig(). The hook returns null when the component is rendered outside a Remotion composition context. Since a waveform is meaningless without a composition, the component throws 'Expected video config' instead of rendering garbage.","triggerScenarios":"AudioWaveformInner (or AudioWaveform) is mounted while useUnsafeVideoConfig() returns null — i.e. outside a <Composition>/player context, or in a part of the Studio tree rendered before composition metadata is available.","commonSituations":"Rendering the component in a Storybook/test harness without a Remotion root; nesting it outside <RemotionRoot>/Sequence context; Studio internal state where no composition is selected; version upgrades that changed context provisioning.","solutions":["Ensure AudioWaveform is only rendered inside a composition context (e.g. within a Sequence/composition subtree in Studio)","Guard the render site: only mount AudioWaveform when a video config is available (check the Studio composition state first)","If used in tests/storybook, wrap the component with the Remotion context providers that supply a video config","Upgrade Remotion Studio packages in lockstep — mismatched @remotion/* versions can leave the context undefined"],"exampleFix":"// before\n<AudioWaveform src={src} />\n// after\n{vidConf ? <AudioWaveform src={src} /> : null}","handlingStrategy":"type-guard","validationCode":"const vidConf = Internals.useUnsafeVideoConfig();\nif (vidConf === null) {\n  // don't render the waveform\n  return null;\n}","typeGuard":"const hasVideoConfig = (c: unknown): c is VideoConfig =>\n  c !== null && typeof c === 'object' && typeof (c as VideoConfig).fps === 'number';","tryCatchPattern":"try {\n  renderWaveform(vidConf);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Expected video config') {\n    setError(err);\n    return null;\n  }\n  throw err;\n}","preventionTips":["Render AudioWaveform only inside a composition/player context","Check useUnsafeVideoConfig() for null before rendering dependent children","Wrap Studio internals with the required context providers in tests/storybook","Keep all @remotion/* packages on the same version"],"tags":["react","context","studio","remotion"],"backgroundTag":"missing-react-context","analyzedSha":"a6a7485a9aeb04219510fbe4874f8941486424df","analyzedAt":"2026-09-02T16:25:19.997Z","contentChangedAt":"2026-09-02T16:25:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}