{"record":{"id":"cc47d330cdb1e2d7","repo":"remotion-dev/remotion","slug":"the-argument-fps-was-not-provided","errorCode":null,"errorMessage":"The argument \"fps\" was not provided","messagePattern":"The argument \"fps\" was not provided","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/media-utils/src/fft/get-visualization.ts","lineNumber":39,"sourceCode":"}: {\n\tsampleSize: number;\n\tdata: Float32Array;\n\tframe: number;\n\tsampleRate: number;\n\tfps: number;\n\tmaxInt: number;\n\toptimizeFor: OptimizeFor;\n\tdataOffsetInSeconds: number;\n}): number[] => {\n\tconst isPowerOfTwo = sampleSize > 0 && (sampleSize & (sampleSize - 1)) === 0;\n\tif (!isPowerOfTwo) {\n\t\tthrow new TypeError(\n\t\t\t`The argument \"bars\" must be a power of two. For example: 64, 128. Got instead: ${sampleSize}`,\n\t\t);\n\t}\n\n\tif (!fps) {\n\t\tthrow new TypeError('The argument \"fps\" was not provided');\n\t}\n\n\tif (data.length < sampleSize) {\n\t\tthrow new TypeError(\n\t\t\t'Audio data is not big enough to provide ' + sampleSize + ' bars.',\n\t\t);\n\t}\n\n\tconst start = Math.floor((frame / fps - dataOffsetInSeconds) * sampleRate);\n\n\tconst actualStart = Math.max(0, start - sampleSize / 2);\n\n\tconst ints = new Int16Array({\n\t\tlength: sampleSize,\n\t});\n\tints.set(\n\t\tdata.subarray(actualStart, actualStart + sampleSize).map((x) => toInt16(x)),\n\t);","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-utils/src/fft/get-visualization.ts#L21-L57","documentation":"Thrown by getVisualization when fps is falsy (0, undefined, NaN, null). The fps is used to convert a frame index into a sample position via frame/fps; a missing or zero fps would divide by zero or produce NaN, so the guard rejects it early.","triggerScenarios":"Calling the visualization API without passing fps, or passing fps: 0. Common when wrapping the API and forgetting to forward the composition's fps, or when fps is read from a config that defaults to 0.","commonSituations":"Remotion composition code that forgets to pass fps from useVideoConfig(). A default fps of 0 in a config object. Reading fps from metadata that failed to load.","solutions":["Always pass a positive fps derived from the composition: const { fps } = useVideoConfig();","Default fps to a sane positive value (e.g. 30) if your API allows it.","Validate fps > 0 before calling getVisualization and surface a clearer error upstream."],"exampleFix":"// before\ngetVisualization({ sampleSize: 128, fps: 0, ... });\n\n// after\nconst { fps } = useVideoConfig();\ngetVisualization({ sampleSize: 128, fps, ... });","handlingStrategy":"validation","validationCode":"if (!fps || fps <= 0) throw new TypeError('fps must be a positive number');\ngetVisualization({ sampleSize, fps, ...rest });","typeGuard":"const isValidFps = (f: unknown): f is number => typeof f === 'number' && f > 0 && Number.isFinite(f);","tryCatchPattern":"try { return getVisualization({ sampleSize, fps, ...rest }); } catch (e) { if (/fps\" was not provided/.test(String((e as Error).message))) { return getVisualization({ sampleSize, fps: 30, ...rest }); } throw e; }","preventionTips":["Always forward useVideoConfig().fps into the visualization API.","Default fps to 30 when its source is unknown.","Validate fps > 0 once at the call boundary."],"tags":["media-utils","fft","visualization","validation","fps"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}