Stirling-Tools/Stirling-PDF · warning · Error
Failed to get canvas context
Error message
Failed to get canvas context
What it means
Thrown by downloadAndOptimizeAvatar() when canvas.getContext('2d') returns null. The 2D rendering context can be unavailable in headless or GPU-constrained browser environments, very old browsers, or when too many canvas contexts are simultaneously allocated. The caller syncOAuthAvatar() catches this and degrades gracefully to the existing avatar.
Source
Thrown at frontend/editor/src/saas/services/avatarSyncService.ts:90
if (!response.ok) {
throw new Error(
`Failed to download avatar: ${response.status} ${response.statusText}`,
);
}
const blob = await response.blob();
// 2. Create image bitmap
const img = await createImageBitmap(blob);
// 3. Create canvas and draw scaled image
const canvas = document.createElement("canvas");
canvas.width = AVATAR_SIZE;
canvas.height = AVATAR_SIZE;
const ctx = canvas.getContext("2d");
if (!ctx) {
throw new Error("Failed to get canvas context");
}
// Draw image scaled to fit (maintains aspect ratio, centered)
const scale = Math.min(AVATAR_SIZE / img.width, AVATAR_SIZE / img.height);
const x = (AVATAR_SIZE - img.width * scale) / 2;
const y = (AVATAR_SIZE - img.height * scale) / 2;
ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
// 4. Convert to PNG blob with quality optimization
return new Promise((resolve, reject) => {
canvas.toBlob(
(optimizedBlob) => {
if (!optimizedBlob) {
reject(new Error("Failed to create optimized blob"));
return;
}
// Check file sizeView on GitHub (pinned to 9ef20dcab8)
Solutions
- Detect canvas 2D support before attempting avatar optimization and skip to raw upload
- Fall back to uploading the unresized blob if canvas is unavailable
- Reduce concurrent canvas operations if the context limit is the cause
- Test in a non-headless browser to confirm the issue is environment-specific
Example fix
// before
const ctx = canvas.getContext("2d");
if (!ctx) {
throw new Error("Failed to get canvas context");
}
// after
const ctx = canvas.getContext("2d");
if (!ctx) {
console.warn("[Avatar Sync] Canvas 2D unavailable, uploading raw blob");
return blob; // skip resize, upload original
} Defensive patterns
Strategy: fallback
Validate before calling
// Detect canvas 2D support before attempting optimization
function hasCanvas2D(): boolean {
try {
const c = document.createElement('canvas');
return c.getContext('2d') !== null;
} catch {
return false;
}
}
if (!hasCanvas2D()) {
return rawBlob; // skip resize
} Try / catch
// syncOAuthAvatar already catches all errors and returns false: // downloadAndOptimizeAvatar throws, but the outer syncOAuthAvatar swallows it. // No additional catch needed if calling through syncOAuthAvatar.
Prevention
- Detect canvas 2D support before attempting avatar optimization and fall back to raw upload
- Test avatar sync in headless/CI environments where canvas may be unavailable
- Never block the user on avatar optimization — always have a graceful degradation path
When it happens
Trigger: Browser running in headless mode without GPU acceleration; browser security/privacy settings disabling canvas (some anti-fingerprinting extensions); extremely memory-constrained environment; old browser without full Canvas 2D support.
Common situations: Headless browser testing (CI/CD, Puppeteer/Playwright) without GPU; user has an anti-fingerprinting extension that blocks canvas context creation; browser under extreme memory pressure.
Related errors
- Failed to download avatar: ${response.status} ${response.sta
- Canvas 2D context unavailable
- Could not get canvas context
- Could not get canvas context
- Failed to decode image
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/b2c172a340fd5664.
Report an issue: GitHub.