{"record":{"id":"d70d900d0c8de9d0","repo":"remotion-dev/remotion","slug":"unknown-fit-fit-d70d90","errorCode":null,"errorMessage":"Unknown fit: ${fit}","messagePattern":"Unknown fit: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gif/src/canvas.tsx","lineNumber":86,"sourceCode":"\t\t\t\tcanvasSize.height / frameSize.height,\n\t\t\t);\n\t\t\tconst centerX = (canvasSize.width - frameSize.width * ratio) / 2;\n\t\t\tconst centerY = (canvasSize.height - frameSize.height * ratio) / 2;\n\n\t\t\treturn [\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tframeSize.width,\n\t\t\t\tframeSize.height,\n\t\t\t\tcenterX,\n\t\t\t\tcenterY,\n\t\t\t\tframeSize.width * ratio,\n\t\t\t\tframeSize.height * ratio,\n\t\t\t];\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error('Unknown fit: ' + fit);\n\t}\n};\n\nconst makeCanvas = () => {\n\tif (typeof document === 'undefined') {\n\t\treturn null;\n\t}\n\n\tconst canvas = document.createElement('canvas');\n\tconst ctx = canvas.getContext('2d');\n\n\tcanvas.width = 0;\n\tcanvas.height = 0;\n\n\treturn ctx;\n};\n\ntype Props = {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/gif/src/canvas.tsx#L68-L104","documentation":"Thrown by the internal `calcArgs` helper in @remotion/gif when the `fit` prop does not match any of the supported values 'contain', 'cover', or 'fill'. The switch statement's `default` branch fires, meaning an unexpected runtime value reached the canvas-sizing logic. TypeScript should normally prevent this because `GifFillMode` is a string-literal union, so hitting it implies the type system was bypassed.","triggerScenarios":"Passing `fit=\"contain \"` (a typo with trailing space), `fit=\"stretch\"`, or a variable typed as `string`/cast with `as any` whose value is outside the union. Also reachable if a future value is added to the prop type but `calcArgs` is not updated.","commonSituations":"Storing the fit value in a config file or URL parameter typed loosely as `string` and passing it straight through; copying a value from CSS `object-fit` (which allows 'none'/'scale-down') that has no GIF equivalent; refactoring that widened the prop type.","solutions":["Only pass one of the literal strings 'contain', 'cover', or 'fill' to `fit`.","Tighten the type of any variable feeding `fit` to `GifFillMode` so the compiler rejects bad values at the call site.","If the value comes from external input, validate/sanitize it against the allowed set before passing it to <Gif>."],"exampleFix":"// before\nconst fit: string = req.query.fit;\n<Gif src={src} fit={fit} />\n\n// after\nimport type {GifFillMode} from '@remotion/gif';\nconst fits: GifFillMode[] = ['contain', 'cover', 'fill'];\nconst fit = fits.includes(req.query.fit) ? req.query.fit : 'contain';\n<Gif src={src} fit={fit} />","handlingStrategy":"type-guard","validationCode":"import type {GifFillMode} from '@remotion/gif';\n\nconst FITS: readonly GifFillMode[] = ['contain', 'cover', 'fill'];\nfunction normalizeFit(value: unknown): GifFillMode {\n  return FITS.includes(value as GifFillMode) ? (value as GifFillMode) : 'contain';\n}","typeGuard":"import type {GifFillMode} from '@remotion/gif';\n\nfunction isGifFillMode(value: unknown): value is GifFillMode {\n  return value === 'contain' || value === 'cover' || value === 'fill';\n}","tryCatchPattern":null,"preventionTips":["Type the variable feeding `fit` as GifFillMode, not string, so the compiler rejects bad values.","When accepting fit from external input (config, URL, JSON), validate it against the literal set before passing it on.","Do not use `as any` to satisfy the prop type; fix the source value instead."],"tags":["gif","validation","typescript","props"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}