{"record":{"id":"940b3c4ae98456cf","repo":"remotion-dev/remotion","slug":"failed-to-acquire-2d-context-for-hue-effect-the-c","errorCode":null,"errorMessage":"Failed to acquire 2D context for hue effect. The canvas may have been assigned a different context type.","messagePattern":"Failed to acquire 2D context for hue effect\\. The canvas may have been assigned a different context type\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/hue.ts","lineNumber":47,"sourceCode":"const validateHueParams = (params: HueParams): void => {\n\tassertEffectParamsObject(params, 'Hue');\n\tassertOptionalFiniteNumber(params.degrees, 'degrees');\n};\n\nexport const hue = createEffect<HueParams, null>({\n\ttype: 'dev.remotion.effects.hue',\n\tlabel: 'hue()',\n\tdocumentationLink: 'https://www.remotion.dev/docs/effects/hue',\n\tbackend: '2d',\n\tcalculateKey: (params) => {\n\t\tconst r = resolve(params);\n\t\treturn `hue-${r.degrees}`;\n\t},\n\tsetup: () => null,\n\tapply: ({source, target, width, height, params}) => {\n\t\tconst ctx = target.getContext('2d');\n\t\tif (!ctx) {\n\t\t\tthrow new Error(\n\t\t\t\t'Failed to acquire 2D context for hue effect. The canvas may have been assigned a different context type.',\n\t\t\t);\n\t\t}\n\n\t\tconst r = resolve(params);\n\n\t\tctx.clearRect(0, 0, width, height);\n\t\tctx.filter = `hue-rotate(${r.degrees}deg)`;\n\t\tctx.drawImage(source, 0, 0, width, height);\n\t\tctx.filter = 'none';\n\t},\n\tcleanup: () => undefined,\n\tschema: hueSchema,\n\tvalidateParams: validateHueParams,\n});\n","sourceCodeStart":29,"sourceCodeEnd":63,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/hue.ts#L29-L63","documentation":"Thrown in the apply() step of the hue effect when target.getContext('2d') returns null. Unlike the WebGL helper-canvas errors, this 'target' is the working canvas the Remotion engine hands to 2D-backend effects, and the message explicitly suggests the canvas may already hold a different (incompatible) context type. A canvas can only host one context family; once it has been given a 'webgl'/'webgl2'/'bitmaprenderer' context, subsequent getContext('2d') calls return null.","triggerScenarios":"The hue effect receiving a target canvas that the engine (or another effect) previously acquired as WebGL or bitmaprenderer; an engine misconfiguration that reuses a canvas across incompatible effect backends.","commonSituations":"Custom integrations that pass the same canvas to both WebGL2-backend and 2D-backend effects; a fork of the Remotion engine that pools canvases naively; mixing hue() after a WebGL2 effect on the same canvas in a hand-rolled pipeline.","solutions":["Give the hue effect a canvas that has never been used with a non-2D context — use a fresh canvas per effect.","If building a custom pipeline, never call getContext('webgl...') and getContext('2d') on the same canvas.","Use the Remotion engine's effect scheduler as-is, which allocates canvases per backend.","Reorder so all 2D-backend effects share one canvas and all WebGL effects share another."],"exampleFix":"// before: same canvas reused across backends\nconst ctx2d = canvas.getContext('2d');     // for hue\nconst gl = canvas.getContext('webgl2');   // earlier, on same canvas\n\n// after: one canvas per backend\nconst canvas2d = document.createElement('canvas');\nconst canvasGl = document.createElement('canvas');","handlingStrategy":"validation","validationCode":"// Ensure the canvas passed to the hue effect has never been acquired as a non-2D context.\nfunction canvasHas2dAvailable(canvas: HTMLCanvasElement): boolean {\n  // Note: calling getContext('2d') itself claims the context, so only call this on a throwaway probe,\n  // or trust the engine to hand each effect a fresh canvas per backend.\n  return canvas.dataset.contextType === undefined || canvas.dataset.contextType === '2d';\n}","typeGuard":null,"tryCatchPattern":"try {\n  hue({ degrees: 90 }).apply({ source, target, width, height, params: { degrees: 90 } });\n} catch (e) {\n  if (e instanceof Error && /Failed to acquire 2D context for hue effect/.test(e.message)) {\n    // target canvas had an incompatible context; allocate a fresh 2D canvas\n  } else throw e;\n}","preventionTips":["Never call getContext('webgl...') and getContext('2d') on the same canvas — a canvas keeps only one context family.","Let the Remotion engine allocate one canvas per effect backend rather than pooling a single canvas yourself.","If you build a custom pipeline, group effects by backend so each canvas stays single-context-family."],"tags":["hue","canvas-2d","context-conflict","backend","integration"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}