Skip to content

Diagnosing issues

In development mode, the Alloy babel transform injects source location metadata (file name, line, column) into every compiled JSX element as an extra argument to createComponent(). This is what powers component stack traces and devtools source links — it is not the same as TypeScript/esbuild source maps.

CommandModeSource info injected?
alloy build --watchdevelopment (default)
alloy buildproduction (default)
alloy build --devdevelopment (explicit)
alloy build --source-infoany✓ (explicit override)

Mode is determined by: CLI flags (--dev/--prod) > BABEL_ENV > NODE_ENV > default (watch → dev, otherwise → prod).

When debugging, use watch mode (alloy build --watch) — it rebuilds incrementally and includes source info by default.

Set ALLOY_TRACE to a comma-separated list of phases to log to the console:

Terminal window
ALLOY_TRACE=symbol,resolve npx vitest run

Each trace line shows a colored phase tag, trace IDs in brackets, and a message.

PhaseWhat it traces
scopecreate, update, delete, copySymbols, moveSymbols
symbolcreate, update, delete, resolve, flow, addToScope, removeFromScope, instantiate, clone
resolvesuccess, pending, failure
effectschedule, track, trigger, effectAdded, effectUpdated, refAdded
renderappendChild, appendComponent, appendMemo, renderEffect, and others

You can also trace a specific sub-area: ALLOY_TRACE=symbol.create,resolve.failure.

Each trace event gets a sequential numeric ID shown in brackets. To pause execution on a specific ID:

Terminal window
ALLOY_TRACE=symbol ALLOY_BREAK_ON_DID=5 node --inspect my-app.js

This inserts a debugger statement when trace event 5 fires. Requires a debugger to be attached (e.g. --inspect or --inspect-brk).

Alloy ships a browser-based devtools for inspecting renders, symbols, effects, and diagnostics in real time.

Terminal window
ALLOY_DEBUG=1 node my-app.js

The server starts on port 8123 (override with ALLOY_DEBUG_PORT). Output:

Alloy <version>
➜ Debug UI: http://localhost:8123/
➜ Websocket: ws://localhost:8123/
Waiting for connection... Connected!

Open the URL in a browser to connect.

With ALLOY_DEBUG=1, render() requires the devtools client to be connected before it runs — otherwise it throws. Use renderAsync() instead, which awaits the devtools connection automatically:

// With ALLOY_DEBUG=1:
await renderAsync(<Output>...</Output>); // ✓ connects then renders
render(<Output>...</Output>); // ✗ throws if devtools not connected

Left panel — file explorer and symbol tree.

Top right — tabbed detail views for files, components, errors, diagnostics, and symbols.

Bottom right — four tabs:

TabShows
Render TreeComponent hierarchy. Click a node to inspect props and children.
ProblemsDiagnostics and errors with component stacks.
EffectsReactive effect graph — tracks, triggers, and dependencies.
TraceLive stream of all trace events with category filters.

The Render Tree panel has Rerender and Rerender + Break buttons on each node, letting you re-trigger a component’s render and optionally pause in the debugger.

ErrorCause
Cannot render without a contextMissing <Output> wrapper around your tree
Source file doesn't have parent directory<SourceFile> not inside an <Output>
ALLOY_DEBUG is set but devtools are not connectedUsed render() instead of renderAsync() with ALLOY_DEBUG=1
Asynchronous jobs were found but render was called synchronouslyAsync work in tree — switch to renderAsync()
Need binder context to create declarations<Declaration> used outside a scope
Can only emit references inside of source files<Reference> used outside <SourceFile>

All render errors include a component stack trace showing the path through your component tree to the error site, with file locations when built in dev mode.

Components can emit diagnostics (info, warning, error) via the diagnostics collector attached to the render context. These appear in the devtools Problems panel and are reported to the console after rendering.

Terminal window
# Trace symbol creation and resolution failures
ALLOY_TRACE=symbol.create,resolve.failure npx vitest run
# Break when trace event #12 fires
ALLOY_TRACE=effect ALLOY_BREAK_ON_DID=12 node --inspect my-app.js
# Devtools on a custom port
ALLOY_DEBUG=1 ALLOY_DEBUG_PORT=9000 node my-app.js