{"record":{"id":"fc8ae58f7314e446","repo":"remotion-dev/remotion","slug":"the-argument-bars-must-be-a-power-of-two-for-ex","errorCode":null,"errorMessage":"The argument \"bars\" must be a power of two. For example: 64, 128. Got instead: ${sampleSize}","messagePattern":"The argument \"bars\" must be a power of two\\. For example: 64, 128\\. Got instead: (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/media-utils/src/fft/get-visualization.ts","lineNumber":33,"sourceCode":"\tsampleRate,\n\tframe,\n\tfps,\n\tmaxInt,\n\toptimizeFor,\n\tdataOffsetInSeconds,\n}: {\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","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-utils/src/fft/get-visualization.ts#L15-L51","documentation":"Thrown by getVisualization when sampleSize (the 'bars' parameter for the audio visualization) is not a power of two. FFT requires input lengths that are powers of two (64, 128, 256, ...); other sizes break the radix-2 algorithm. The guard checks sampleSize > 0 && (sampleSize & (sampleSize - 1)) === 0.","triggerScenarios":"Passing a numberOfBars/sampleSize value that is zero, negative, or not a power of two (e.g. 100, 50, 7) to the visualization/FFT API. The bit-trick check immediately rejects it before any FFT math runs.","commonSituations":"Letting user input dictate the bar count without rounding to a power of two. Copying a snippet that used a non-FFT visualization with arbitrary counts. Config-driven components where a designer set bars: 100.","solutions":["Use a power-of-two value: 32, 64, 128, 256, 512, 1024, 2048.","If accepting arbitrary user input, snap it to the nearest power of two before passing it in.","Compute the next power of two: Math.pow(2, Math.round(Math.log2(n)))."],"exampleFix":"// before\nconst viz = getVisualization({ sampleSize: 100, ... });\n\n// after\nconst sampleSize = Math.pow(2, Math.round(Math.log2(100))); // 128\nconst viz = getVisualization({ sampleSize, ... });","handlingStrategy":"validation","validationCode":"function assertPowerOfTwo(n: number) { if (!(n > 0 && (n & (n - 1)) === 0)) throw new TypeError('bars must be a power of two'); }\nassertPowerOfTwo(sampleSize);","typeGuard":"const isPowerOfTwo = (n: number): boolean => n > 0 && (n & (n - 1)) === 0;","tryCatchPattern":"try { return getVisualization({ sampleSize, ...rest }); } catch (e) { if (/power of two/.test(String((e as Error).message))) { sampleSize = Math.pow(2, Math.round(Math.log2(sampleSize))); return getVisualization({ sampleSize, ...rest }); } throw e; }","preventionTips":["Snap arbitrary bar counts to the nearest power of two before calling.","Whitelist allowed sizes: [32, 64, 128, 256, 512, 1024, 2048].","Validate UI inputs before forwarding to the FFT API."],"tags":["media-utils","fft","visualization","validation","audio"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}