Debugging

Finch includes a built-in browser debugging bar for local development. When enabled, a collapsible panel appears at the bottom of every rendered page, giving you real-time insight into the current request without leaving the browser.

The debug bar shows:

  • Registered routes and which one matched the current request
  • Request details (method, path, headers, session, cookies)
  • Template parameters passed to the current view
  • Server logs and errors for the current request
  • Buttons to reload the page or restart the server

Enabling the Debugger

Two conditions must both be true for the debugger to activate:

  1. enableLocalDebugger: true in FinchConfigs — this allows the debugger to run at all.
  2. isLocalDebug returns true — this indicates the app is currently running in development mode.

isLocalDebug is computed automatically:

  • If the environment variable LOCAL_DEBUG is set, it uses that value (true/false).
  • Otherwise it checks Console.isDebug, which is true when the app is run with dart run (not compiled with dart compile exe).

In app.dart:

FinchConfigs configs = FinchConfigs(
  // Allow the debugger to be shown when running in debug mode
  enableLocalDebugger: (env['ENABLE_LOCAL_DEBUGGER'] ?? false).toString().toBool,
);

In your .env file (development):

ENABLE_LOCAL_DEBUGGER=true
LOCAL_DEBUG=true

In production, both should be false (or simply omit them, as the defaults are false).

How It Works

When enableLocalDebugger && isLocalDebug, Finch:

  1. Injects debug data into every renderView() response.
  2. Appends the debug bar HTML at the bottom of the page.
  3. Exposes a WebSocket-based live-reload endpoint.

The debug bar is never injected when:

  • enableLocalDebugger is false
  • isLocalDebug is false
  • The response is JSON (renderData()) or plain text (renderString())

Checking Debug Mode in Code

You can read isLocalDebug in your controller or template to conditionally show development-only content:

// In a controller
if (FinchApp.config.isLocalDebug) {
  Console.p('Debug: current user is ${rq.getSession("user")}');
}
<!-- In a template -->
{% if isLocalDebug %}
  <p class="debug-note">Running in debug mode</p>
{% endif %}

isLocalDebug is automatically injected as a template variable for every renderView() call, so no rq.addParam() is needed.

Error Pages

In debug mode, error pages (e.g., 404, 500) include a full stack trace to help diagnose the issue. In production mode, error pages show only a user-friendly message without internal details.