Skip to content

Debugging Guide

Open the editor to debug issues live.

Common Errors

"No entry file found"

The project needs exactly one entry file. The default is main.js (shown with an entry badge). You cannot change entry in the UI — put your return in that file.

"Module 'xxx' not found"

Import specifier must match a file name in the explorer (with or without .js):

javascript
import { helper } from './utils';  // needs utils or utils.js

"Circular import detected"

A imports B and B (directly or indirectly) imports A. Extract shared code into a third leaf module.

Syntax errors / "Unexpected token"

Typical causes:

  • Missing } or )
  • Default or namespace imports (only named imports are supported)
  • Multiline import { ... } (keep on one line)
  • Top-level await

Named import { ... } from './file' is allowed in the entry file.

"xxx is not defined"

Only time, dt, state, w, h, and your imports exist in the entry. Modules do not see frame globals — pass them as arguments.

javascript
// BUG
return { particles: [{ x: x, y: 100 }] };

// FIX
const x = 100;
return { particles: [{ x, y: 100 }] };

"Cannot read property of undefined"

Missing init:

javascript
if (!state.init) {
  state.particles = [];
  state.init = true;
}
state.particles.push({ x: 100, y: 100 });

Simulation Behavior

Particle stays still

Position overwritten every frame, or using let instead of state:

javascript
state.x = (state.x ?? 100) + 50 * dt;

Particle teleports

Forgot dt:

javascript
state.x += 50 * dt;  // not state.x += 50

Jump after tab switch

dt is clamped to 50ms. If you still see jumps, check for custom time accumulation that ignores the clamp.

Nothing renders

You must return a FrameResult. While paused, the host stops the frame callback — expect a cleared canvas with grid/axes only.

Edits reset the sim

Recompile (~400ms after typing stops) clears state and time. That is intentional. Use Pause to freeze without clearing; Restart to clear without changing code.

Click does nothing

javascript
if (state.clickX !== undefined) {
  // handle
  state.clickX = undefined;
  state.clickY = undefined;
}

Avoid truthy checks alone if 0 could be a valid coordinate (rare, but !== undefined is safer).

Performance

  1. Cap primitive counts (see Performance Guidelines).
  2. Bound trail / particle arrays.
  3. Prefer squared distances in hot loops:
javascript
const perceptionSq = r * r;
const distSq = dx * dx + dy * dy;
if (distSq < perceptionSq) { /* ... */ }
  1. Show frame cost in the HUD:
javascript
return { text: { dt: (dt * 1000).toFixed(1) + 'ms' } };

Consistently > 16ms means the frame is overloaded.

Editor Issues

Code doesn't update

Wait for the 400ms debounce after typing.

Error won't clear

Fix the code, or click Restart. Persistent errors are real compile/runtime failures.

Red squiggles in Monaco

TypeScript does not know about injected globals. Squiggles are usually false positives. Add // @ts-nocheck at the top if they distract you.

Restart vs Reset

RestartReset
CodeKeptRestored to starter main.js
state / timeClearedCleared