linshenkx/prompt-optimizer · error · Error
Canvas is not available
Error message
Canvas is not available
What it means
Thrown by ensureCanvas in packages/ui/src/utils/favorite-share-export.ts when neither the provided canvasFactory nor document.createElement('canvas') yields an object with a getContext method. This is an environment-capability guard: in normal browsers a canvas always has getContext, so hitting it means canvas support is absent or the factory returned something invalid. It fires before any 2D rendering begins.
Source
Thrown at packages/ui/src/utils/favorite-share-export.ts:932
} else {
fail();
}
});
}());
</script>
</body>
</html>`
return {
blob: new Blob([html], { type: 'text/html;charset=utf-8' }),
result,
}
}
const ensureCanvas = (canvasFactory?: () => HTMLCanvasElement): HTMLCanvasElement => {
const canvas = canvasFactory?.() || document.createElement('canvas')
if (!canvas.getContext) {
throw new Error('Canvas is not available')
}
return canvas
}
const wrapCanvasText = (
context: CanvasRenderingContext2D,
text: string,
maxWidth: number,
): string[] => {
const lines: string[] = []
for (const rawLine of text.split(/\r?\n/)) {
const words = rawLine.split(/(\s+)/).filter(Boolean)
let line = ''
for (const word of words) {
if (context.measureText(word).width > maxWidth) {
for (const char of Array.from(word)) {
const next = `${line}${char}`
if (line && context.measureText(next).width > maxWidth) {View on GitHub (pinned to 3e677b1d9f)
Solutions
- If in tests, pass a canvasFactory returning a real or adequately mocked canvas (with getContext and a 2D context stub)
- Guard the export call: only invoke PNG share export when typeof document !== 'undefined' and document.createElement('canvas').getContext exists
- In SSR, run the export only after mount in the browser, or use a node-canvas-backed factory
- Fix a canvasFactory that returns a non-canvas object (e.g. a context instead of the canvas)
Example fix
// before
const canvas = ensureCanvas(() => fakeCanvasStub) // stub lacks getContext -> throws Canvas is not available
// after
const canvas = ensureCanvas(() => realCanvas) // or omit factory in a real browser DOM
const context = canvas.getContext('2d')
if (!context) throw new Error('Canvas 2D context is not available') Defensive patterns
Strategy: validation
Validate before calling
const canUseCanvas = (): boolean =>
typeof document !== 'undefined' &&
typeof document.createElement === 'function' &&
typeof document.createElement('canvas').getContext === 'function'
if (!canUseCanvas()) {
// hide PNG share button or fall back to text sharing
} Type guard
const isCanvasLike = (el: unknown): el is HTMLCanvasElement => typeof el === 'object' && el !== null && typeof (el as HTMLCanvasElement).getContext === 'function'
Try / catch
try {
const blob = await exportFavoriteSharePng(options)
} catch (e) {
if (e instanceof Error && e.message === 'Canvas is not available') {
// fall back to text-only share, or disable the feature in this environment
return
}
throw e
} Prevention
- Only trigger share-image export in a real browser DOM (guard typeof document)
- In tests, pass a canvasFactory returning a properly mocked canvas
- Don't invoke canvas export paths during SSR; defer to client-side after mount
- Ensure canvasFactory returns the canvas element itself, not a context or null
When it happens
Trigger: Running the PNG share-image export in an environment without DOM/canvas (SSR, Node, jsdom, Web Workers without DOM access); passing a canvasFactory that returns null, undefined, a plain object, or a detached mock lacking getContext; or an environment where HTMLCanvasElement is not implemented.
Common situations: Unit tests in jsdom that trigger image export; server-side rendering paths that accidentally call share-image generation; mocking document.createElement without providing getContext; embedded webviews with canvas disabled. Note the factory result is used as-is, so a falsy factory result silently falls back to document.createElement — the error only fires when both paths fail.
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/903cbb432a989893.
Report an issue: GitHub.