{"record":{"id":"46bbcfbe5d6b2a38","repo":"remotion-dev/remotion","slug":"failed-to-acquire-2d-context-for-invert-effect-th","errorCode":null,"errorMessage":"Failed to acquire 2D context for invert effect. The canvas may have been assigned a different context type.","messagePattern":"Failed to acquire 2D context for invert effect\\. The canvas may have been assigned a different context type\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/invert.ts","lineNumber":51,"sourceCode":"\n\tconst {amount} = resolve(params);\n\tvalidateUnitInterval(amount, 'amount');\n};\n\nexport const invert = createEffect<InvertParams, null>({\n\ttype: 'dev.remotion.effects.invert',\n\tlabel: 'invert()',\n\tdocumentationLink: 'https://www.remotion.dev/docs/effects/invert',\n\tbackend: '2d',\n\tcalculateKey: (params) => {\n\t\tconst r = resolve(params);\n\t\treturn `invert-${r.amount}`;\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 invert 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 = `invert(${r.amount * 100}%)`;\n\t\tctx.drawImage(source, 0, 0, width, height);\n\t\tctx.filter = 'none';\n\t},\n\tcleanup: () => undefined,\n\tschema: invertSchema,\n\tvalidateParams: validateInvertParams,\n});\n","sourceCodeStart":33,"sourceCodeEnd":67,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/invert.ts#L33-L67","documentation":"Thrown in the apply() step of the invert effect when target.getContext('2d') returns null. Identical mechanism to the hue effect: the target canvas was already assigned a non-2D context type (webgl/webgl2/bitmaprenderer), and a canvas can only hold one context family. The message names the invert effect for clarity but the root cause is canvas/context reuse across backends.","triggerScenarios":"The invert effect receiving a target canvas previously acquired as WebGL or bitmaprenderer; an engine or custom pipeline that pools one canvas across incompatible backends.","commonSituations":"Custom integrations passing the same canvas to both WebGL2 and 2D-backend effects; hand-rolled effect pipelines that reuse a canvas; a forked engine with naive canvas pooling.","solutions":["Provide a fresh canvas to the invert effect that has never been used with a non-2D context.","Never call getContext('webgl...') and getContext('2d') on the same canvas.","Use the Remotion engine's scheduler unchanged; it allocates canvases per backend.","Group effects by backend so each canvas stays single-context-family."],"exampleFix":"// before: same canvas reused across backends\nconst gl = canvas.getContext('webgl2');   // earlier\nconst ctx2d = canvas.getContext('2d');    // for invert -> null\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 invert effect has never been acquired as a non-2D context.\nfunction canvasHas2dAvailable(canvas: HTMLCanvasElement): boolean {\n  return canvas.dataset.contextType === undefined || canvas.dataset.contextType === '2d';\n}","typeGuard":null,"tryCatchPattern":"try {\n  invert({ amount: 1 }).apply({ source, target, width, height, params: { amount: 1 } });\n} catch (e) {\n  if (e instanceof Error && /Failed to acquire 2D context for invert 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 holds only one context family.","Let the Remotion engine allocate canvases per backend; do not pool one canvas across effects.","In custom pipelines, group effects by backend so each canvas stays single-context-family."],"tags":["invert","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"}