# SpacetimeDB Debugging and Troubleshooting Tips: Complete Guide to Logging and Diagnostics

> Master SpacetimeDB debugging with our comprehensive guide to logging and diagnostics. Stream logs in real-time, inspect programmatically, and debug reducers effectively.

- Repository: [Clockwork Labs/SpacetimeDB](https://github.com/clockworklabs/SpacetimeDB)
- Tags: how-to-guide
- Published: 2026-03-09

---

**SpacetimeDB ships with a unified, tiered logging architecture that spans from low-level WASM host operations to client-side CLI tools, enabling developers to debug reducers via real-time log streaming, programmatic inspection, and debug builds without exposing sensitive user data.**

The clockworklabs/SpacetimeDB repository provides a comprehensive diagnostic system that unifies logging across Rust, TypeScript, and C# modules. Understanding how the **database logger**, **host injection layer**, and **CLI tools** interact allows you to quickly isolate faulty reducers, filter noise in production, and monitor system health.

## Understanding the SpacetimeDB Logging Architecture

The platform implements a five-layer logging stack that transports diagnostic messages from your module code to your terminal or test harness. Each layer is designed to work seamlessly across language boundaries.

### Core Logging Layers

- **Database Logger**: Located in [`crates/core/src/database_logger.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/core/src/database_logger.rs), this service stores log records per replica and exposes a `tail` API. It defines the `LogLevel` enum and the `write` routine that transforms a `Record` struct into a `LogEvent`.

- **Host-Side Injection**: The `inject_logs` method in [`crates/core/src/host/module_host.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/core/src/host/module_host.rs) is called from generated reducer wrappers, automatically forwarding diagnostics from your business logic to the logger.

- **Console Bridge**: Found in [`crates/core/src/host/instance_env.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/core/src/host/instance_env.rs), this layer intercepts WASM syscalls such as `console.log` and `console.debug`, mapping them to the appropriate `LogLevel` before transmission.

- **CLI Log Viewer**: The `spacetime logs` command, implemented in [`crates/cli/src/subcommands/logs.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/cli/src/subcommands/logs.rs), streams output from the database logger and supports `--level`, `--since`, and `--follow` flags.

- **Programmatic Access**: The testing harness in [`crates/testing/src/modules.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/testing/src/modules.rs) exposes `ModuleHandle::read_log`, which calls `client.module().database_logger().tail` to fetch records directly without CLI overhead.

## Essential Debugging Workflows

### Emit Logs at the Appropriate Severity Level

Use **debug-level** logging for transient diagnostics, **info** for normal events, **warn** for recoverable anomalies, and **error** for failures that abort a reducer. The logger automatically prefixes records with the reducer name and timestamp.

**Rust Example:**

```rust
use spacetimedb::{reducer, ReducerContext};

#[reducer]
pub fn transfer(ctx: &ReducerContext, from: u64, to: u64, amount: u32) -> Result<(), String> {
    log::info!("Transfer request: {} → {} ({})", from, to, amount);
    if amount == 0 {
        log::warn!("Zero-amount transfer requested by {}", ctx.sender);
    }
    log::debug!("Reducer invoked by {} with ctx={:?}", ctx.sender, ctx);
    Ok(())
}

```

**TypeScript Example:**

```typescript
import { spacetimedb } from 'spacetimedb/server';

spacetimedb.reducer('processData', { value: t.u32() }, (ctx, { value }) => {
  console.debug(`processData called by ${ctx.sender}, value=${value}`);
  console.log(`Processing ${value}`);
});

```

**C# Example:**

```csharp
using SpacetimeDB;

public static partial class Module
{
    [SpacetimeDB.Reducer]
    public static void ProcessData(ReducerContext ctx, uint value)
    {
        Log.Debug($"ProcessData called by {ctx.Sender}, value={value}");
        Log.Info($"Processing {value}");
    }
}

```

### Build with Debug Mode for Fast Iteration

Compile your Wasm module with debug symbols and no optimizations to speed up the edit-run cycle. This does not affect production builds.

```bash
spacetime build --debug

```

### Stream Logs in Real-Time with the CLI

Use the `--follow` flag to stream new records as they are written, similar to `tail -f`. Combine with `--level` to focus on specific severities.

```bash

# Stream only warnings and errors

spacetime logs --follow --level warn my-game-db

```

### Filter Logs by Time Windows

When investigating events that occurred at specific times, use `--since` with an ISO-8601 timestamp to replay the relevant slice.

```bash
spacetime logs --since "2024-10-01T12:00:00Z" my-game-db

```

### Access Logs Programmatically in Tests

Avoid race conditions in integration tests by reading logs directly through the client API rather than shelling out to the CLI.

```rust
let logs = module_handle.read_log(Some(100)).await; // fetch up to 100 recent lines
println!("Recent logs:\n{logs}");

```

This method is implemented in [`crates/testing/src/modules.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/testing/src/modules.rs) as `ModuleHandle::read_log`.

## Troubleshooting Common Issues

### Missing Reducer Logs

If logs do not appear, ensure your reducer function is compiled with the correct attribute. In Rust, verify the `#[reducer]` macro is present; in TypeScript, ensure the function is registered with `spacetimedb.reducer`. These macros inject the necessary `inject_logs` calls.

### No Output in Production

By default, the global log level is set to `info`. To capture debug output in a deployed database, modify [`standalone.toml`](https://github.com/clockworklabs/SpacetimeDB/blob/main/standalone.toml) to set `logs.level = "debug"` or use the CLI:

```bash
spacetime config set logs.level debug

```

### Interpreting Panic-Level Logs

Panic logs indicate unrecoverable internal errors, such as host-side invariant violations. These bypass all filters and appear regardless of the `logs.level` setting. Consult the `target` field in the log record to identify the specific module function that caused the failure.

## Summary

- **SpacetimeDB** provides a unified logging system across Rust, TypeScript, and C# modules via the database logger in [`crates/core/src/database_logger.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/core/src/database_logger.rs).

- Use `spacetime build --debug` for rapid development iterations with full symbol information.
- Stream and filter logs using `spacetime logs` with `--follow`, `--level`, and `--since` flags.
- Access logs programmatically in tests via `ModuleHandle::read_log` to avoid CLI race conditions.
- Configure production logging levels in [`standalone.toml`](https://github.com/clockworklabs/SpacetimeDB/blob/main/standalone.toml) or via `spacetime config set logs.level`.
- Panic-level messages bypass filters and indicate critical internal errors requiring immediate attention.

## Frequently Asked Questions

### How do I enable debug logging in a production SpacetimeDB database?

Set the `logs.level` configuration to `"debug"` either by editing the [`standalone.toml`](https://github.com/clockworklabs/SpacetimeDB/blob/main/standalone.toml) configuration file or by running `spacetime config set logs.level debug`. By default, production environments filter to `info` level and above to reduce noise.

### Why are my reducer logs not appearing in the output?

Ensure your reducer function is properly decorated with the language-specific attribute, such as `#[reducer]` in Rust or `[SpacetimeDB.Reducer]` in C#. These macros generate the `inject_logs` calls found in [`crates/core/src/host/module_host.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/core/src/host/module_host.rs) that bridge your code to the logging system.

### What is the difference between `spacetime logs --follow` and programmatic log access?

The `--follow` flag provides a human-readable stream suitable for active development monitoring, while programmatic access via `ModuleHandle::read_log` in [`crates/testing/src/modules.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/testing/src/modules.rs) returns structured data directly to your test code, eliminating race conditions between the test execution and CLI polling.

### How do I interpret panic-level log messages?

Panic logs indicate unrecoverable internal errors, such as WASM host invariant violations, and bypass all severity filters. Each panic record includes a `target` field pointing to the specific module function responsible and a stack trace in the message body. These require immediate code review as they represent system-level failures rather than application errors.