Console
Logging from inside the sandbox: what console.log, warn and error do, where entries surface and what they never touch.
The sandbox console (log/warn/error). Values stringify like the host console; entries are per-evaluation diagnostics, echoed - never rendered.
log
log(...values: unknown[]): void
Records a log-level entry.
Worked example: Narrate your numbers
The scene. One orange square resting on a dark 640 by 360 stage.
- The comp Drift: 640 by 360 at 25 fps, 100 frames (4 seconds).
- Square: a solid layer, at [320, 180], 60 by 60, filled f2a833.
The script. Add a project script named Narrator and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame({ frame, fps }) {
const level = frame % fps === 0 ? 100 : 82;
console.log("frame", frame, "level", level);
return level;
}
Line by line:
- Line 4: A pulse: full strength on each whole second, 82 otherwise.
- Line 5: console.log() records values for YOU - the IDE's live preview strip echoes them while you type, and the farm's status surfaces keep them for a failing render. Logs never touch pixels, and only the first 100 entries per evaluation are kept.
What you see. The square pulses to full strength on every whole second while the console narrates each frame's level - diagnostics beside the picture, never in it.
warn
warn(...values: unknown[]): void
Records a warn-level entry.
Worked example: Warn when you clip
The scene. One orange square resting on a dark 640 by 360 stage.
- The comp Drift: 640 by 360 at 25 fps, 100 frames (4 seconds).
- Square: a solid layer, at [320, 180], 60 by 60, filled f2a833.
The script. Add a project script named Clip guard and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
const requested = 140;
if (requested > 100) {
console.warn("opacity clipped from", requested);
}
return Math.min(requested, 100) - 25;
}
Line by line:
- Lines 4-7: Opacity only accepts 0 to 100 - returning 140 would refuse with the typed type_mismatch. The guard clips the value itself and uses console.warn() to leave a note that it did, so future-you knows why the number on screen is not the number in the code.
- Line 8: The clipped 100 minus 25 rests the Square at 75.
What you see. The square rests at 75 percent while the console carries a warning that the requested 140 was clipped - the script degrades politely and says so.
error
error(...values: unknown[]): void
Records an error-level entry.
Worked example: Shout, then carry on
The scene. One orange square resting on a dark 640 by 360 stage.
- The comp Drift: 640 by 360 at 25 fps, 100 frames (4 seconds).
- Square: a solid layer, at [320, 180], 60 by 60, filled f2a833.
The script. Add a project script named Empty-list lament and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
const marks = [];
if (marks.length === 0) {
console.error("no marks configured - resting at 60");
return 60;
}
return 100;
}
Line by line:
- Lines 4-8: console.error() is the loudest note - use it when the script detects a state it considers wrong but can still render something sensible. Erroring OUT LOUD by throwing would drop every output back to base for the frame; logging an error and returning a fallback keeps the picture alive AND the complaint on record.
What you see. The square rests at the 60 percent fallback while the console carries the script's complaint about its empty configuration - visible failure notes without a broken frame.