Diagnosing Blank p5.js Sketches: Canvas, Loop, and Asset Failures
When a p5.js sketch renders nothing or freezes, the cause usually lies in canvas initialization, the draw loop, instance-mode scope, or asset preloading. Use ordered checks to isolate the layer that failed.
01 Dec 2025, 08:13 UTC

Start With the Console and the DOM
A blank p5.js sketch almost never fails silently. Before changing code, open your browser's developer tools. If the console shows createCanvas is not defined or draw is not a function, the problem is structural: a required function is missing or misspelled. If the console is clean but nothing renders, inspect the Elements panel for a <canvas> element. Its absence means setup() never created one; its presence with correct width and height means the canvas exists but the drawing logic is not executing.
Recognizable Conditions and Likely Causes
| Condition | Likely Cause | Fastest Check |
|---|---|---|
| No canvas appears | createCanvas() missing, called outside setup(), or given invalid dimensions | Elements panel for <canvas> |
| Canvas exists but stays blank | draw() undefined, empty, or blocked by an early return or thrown error | Console errors; temporary background() call |
| Shapes misplaced or missing | Instance mode used without this (or p.) references; global variables assumed in instance mode | Console log scope inside draw() |
| Animation frozen after first frame | noLoop() called, frameRate(0), or a synchronous blocking operation inside draw() | Comment out noLoop(); verify frameRate value |
| Assets missing or load hangs | No preload() function, failed fetch, or Content Security Policy blocking requests | Network tab; console CSP errors |
Ordered Checks
- Check the browser console. Look for
ReferenceErrororTypeErrormessages. A missingcreateCanvasordrawerror points directly to the failing function. - Verify the canvas element. In the Elements panel, search for
<canvas>. If it is absent,setup()did not run or did not callcreateCanvas(). If it exists, confirm the width and height attributes are positive integers. - Insert a temporary diagnostic draw. Add
background(220)andconsole.log('drawing')as the first lines ofdraw(). If the background appears but shapes do not, the issue is in your drawing logic. If nothing appears,draw()is not running. - Test the loop state. Search your code for
noLoop()andframeRate(0). Temporarily comment them out and reload. If animation resumes, you found the cause. - Audit scope in instance mode. If you used
new p5(sketch), confirm every p5 method and property is prefixed with the instance variable (commonlyporthis). A missing prefix causesReferenceErroror silently reads from the wrong object. - Check asset loading. Open the Network tab and reload. Confirm preloaded images, fonts, or sounds return status 200. If they are blocked or pending, the sketch may be stuck before
setup()completes.
Fixes Tied to Findings
Canvas Never Appears
Ensure createCanvas() is called inside setup() with positive integer arguments. Calling it after setup() has returned, or passing zero, negative, or non-numeric values, prevents initialization.
function setup() {
createCanvas(400, 400); // must run inside setup
}
Canvas Exists but Nothing Draws
Define a draw() function. Remove unconditional early return statements that prevent rendering. If an error is thrown mid-function, execution stops; fix the first reported error before investigating later lines.
Instance Mode Scope Errors
In instance mode, p5 methods and variables are not global. They belong to the instance passed to your sketch function. The following example shows the difference:
// Global mode: methods are global
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
ellipse(mouseX, mouseY, 50, 50);
}
// Instance mode: every reference needs the instance prefix
const sketch = (p) => {
p.setup = () => {
p.createCanvas(400, 400);
};
p.draw = () => {
p.background(220);
p.ellipse(p.mouseX, p.mouseY, 50, 50);
};
};
new p5(sketch);
If you write ellipse(mouseX, mouseY, ...) inside the instance-mode draw(), the browser throws ReferenceError: mouseX is not defined because mouseX is not a global variable in that scope.
Animation Frozen
Remove or conditionally guard noLoop(). Ensure frameRate() receives a positive number. Move any synchronous, long-running operations—such as large array computations or blocking network requests—out of draw() and into setup() or asynchronous callbacks.
Assets Not Loading
Define a preload() function and assign results to variables. Verify file paths are relative to the HTML file or absolute URLs. If the console reports Content Security Policy violations, either adjust the CSP header to allow the asset origin or serve files from the same origin as the sketch.
Version and Environment Cautions
p5.js changed behavior between v1.4 and v1.5, particularly around pixelDensity() and instance-mode internals. If your sketch relies on high-DPI scaling or embeds p5 in a larger application, verify the version you are loading and test against the documented behavior for that release. External libraries that overwrite the global p5 variable can also break sketches that assume global mode; isolate p5 usage in a dedicated script block or module.
Escalation Criteria
Escalate to a minimal reproduction or file an issue when:
- The console shows CSP violations you cannot resolve through headers or asset placement.
- A third-party library appears to overwrite the global
p5object. - The sketch fails only on a specific p5.js version and you have confirmed the version-specific documentation.
- All ordered checks pass but the canvas still renders incorrectly.
For escalation, strip the sketch down to a single setup() and draw() that calls background() and one shape. If that minimal case fails, the problem is environmental (script loading order, CSP, version conflict) rather than in your drawing logic.
Practical Verification
After applying a fix, reload the page and confirm three signals: the <canvas> element exists with the intended dimensions, the console is free of errors, and a temporary console.log inside draw() fires repeatedly (unless you intentionally called noLoop()). Remove the diagnostic background() and log statements once the sketch behaves correctly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.