Skip to content

Debugging

iKryptonic edited this page May 1, 2026 · 6 revisions

Debugging

A complete debugging guide for the current runtime: how to use ServiceManager, what each tab is for, which console commands exist, where performance data lives, and how to diagnose the most common failures.

Important

This page is based on the current implementations of Logger, Scheduler, BaseEntity, BaseStateMachine, NetworkManager, ServiceManager, ConsoleModule, AnalyticsEngine, and the shipped ServiceManager tests.


1. The fastest debugging workflow

For most problems, use this order:

  1. read the Luau output for boot or runtime errors
  2. open ServiceManager on a client in Studio
  3. switch to server context if the bug is authoritative
  4. inspect the right tab instead of guessing
  5. use console commands for focused probes
  6. cross-check profiler and entity/FSM data before changing code
┌────────────────────────┐
│ Something looks wrong │
└────────────┬───────────┘
             ▼
┌─────────────────────────────────┐
│ Boot failure or runtime failure?│
└──────────────┬─────────────┬────┘
               │ Boot        │ Runtime
               ▼             ▼
┌───────────────────────────────────┐   ┌─────────────────────┐
│ Check Studio output + Logger history │ │ Open ServiceManager │
└───────────────────────────────────┘   └──────────┬──────────┘
                                                    ▼
                                      ┌──────────────────────┐
                                      │ What kind of issue? │
                                      └──────┬─────┬────┬────┬──────────────┘
                                             │     │    │    │
                                             │     │    │    └─ need targeted query ─→ [CONSOLE tab]
                                             │     │    └────── lag or budget spike ─→ [TASKS / PROFILER / INSIGHTS]
                                             │     └─────────── network payload weird ─→ [NETWORK tab]
                                             └──────────────── entity data wrong ─────→ [ENTITY tab]
                                                               FSM stuck or wrong state ─→ [FSM tab]

[FSM tab] ───────────────┐
[ENTITY tab] ────────────┼─→ [Check transition history + state duration]
[NETWORK tab] ───────────┤
[TASKS / PROFILER / INSIGHTS] ─┤
[CONSOLE tab] ────────────┘

2. Boot the dashboard correctly

ServiceManager is a client-side tool. The usual development bootstrap is:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Orchestrator = require(ReplicatedStorage:WaitForChild("Orchestrator", 30))

Orchestrator:RegisterComponents()

if RunService:IsStudio() then
    local sm = Orchestrator:StartServiceManager()
    sm.SwitchSubsystem("FSM")
    sm.SetContextMode("server")
end

What StartServiceManager() does

  • requires ServiceManager/init.luau
  • initializes the GUI, store, behavior tree, analytics engine, navigator, and subsystem modules
  • shows the window
  • defaults to TASKS if nothing is selected yet

What it does not do

  • it does not replace RegisterComponents()
  • it does not boot the framework by itself
  • it does not automatically choose the right context for your bug

3. Understand client vs. server context

ServiceManager runs in strict context modes:

  • client
  • server

Switch with either API or console:

sm.SetContextMode("server")

or:

mode server

What happens on context switch

The current implementation does all of the following:

  • updates nexus.mode in the reactive store
  • updates the GUI status bar
  • forces a synchronous poll of ServiceManager_ServerSnapshot when entering server mode
  • drops stale drill-down layers
  • pushes a divider into the console output (context: CLIENT → SERVER)
  • resets perf-strip smoothing to avoid graph corruption across contexts

Polling cadence

The client polls the server snapshot:

  • every 2 seconds in server mode
  • every 5 seconds in client mode

If you are debugging an authoritative problem and the list looks stale, switch to server mode first.


4. All 9 ServiceManager tabs and how to use them

4.1 TASKS

Best for:

  • scheduler health
  • verifying the global heartbeat exists
  • per-task status (active / idle / archived / completed)
  • quick “what is hot right now?” checks

Things to inspect:

  • GlobalStateMachineHeartbeat
  • ServiceManagerBrainTick
  • execution counts
  • average and max run time
  • event bucket (Heartbeat, etc.)
  • whether a task is recurring

Use TASKS first when:

  • FSMs are not updating
  • work seems stuck
  • performance cost seems task-oriented instead of state-oriented

4.2 FSM

Best for:

  • current state
  • transition history
  • completed/failed machine inspection
  • stall detection
  • state graph visualization

Particularly useful fields:

  • CurrentState
  • TransitionCount
  • StateDuration
  • TransitionHistory
  • Error
  • IsStalled
  • per-FSM Perf

The current module also keeps client-side and server-side shadow caches so you can inspect finished machines that have already been unregistered from the live registry.

4.3 ENTITY

Best for:

  • checking whether the server and client agree on state
  • version drift
  • replication flags
  • schema shape
  • whether an entity is still valid

Especially useful for diagnosing:

  • “my door opened on the server but not on the client”
  • UpdateEntity() appearing to succeed but visuals not reacting
  • version gaps or stale updates

4.4 NETWORK

Best for:

  • EntityUpdateEvent
  • EntityCommandEvent
  • OrchestratorEvent
  • OrchestratorFunction
  • event bus traffic
  • server request callbacks

The current implementation keeps structured ArgsStruct style payload snapshots for drill-down, which is much better than raw {table} spam.

4.5 DATASTORE

Best for:

  • persistent entities
  • save/load visibility
  • checking whether the expected persistence layer is even online

If your issue is “state disappears between sessions”, this is the tab to pair with logs.

4.6 INSIGHTS

Best for:

  • anomaly detection
  • memory pressure warnings
  • stalled FSMs
  • slow task bottlenecks
  • too many render-priority FSMs
  • dead entity backlog
  • FPS degradation

The current AnalyticsEngine registers 10 built-in rules, including:

  • FSM state stall detection (> 30s)
  • high-frequency task bottlenecks (> 8ms avg)
  • entity count spike (> 500)
  • memory pressure (> 512 MB)
  • render-priority overuse (> 10 render-priority FSMs)
  • orphaned event buses
  • failed FSM clusters
  • zero-activity scheduler
  • dead entity backlog
  • frame rate degradation (< 30 FPS)

4.7 CONSOLE

Best for:

  • focused text queries
  • toggling modes
  • listing tasks/FSMs/entities quickly
  • grabbing a quick perf snapshot without leaving the tab

The console keeps:

  • a 500-line output ring buffer
  • 100 commands of input history
  • autocomplete for commands, subcommands, and dynamic IDs

4.8 LOGS

Best for:

  • structured log history
  • browsing warnings and errors without relying on the Studio output window alone
  • checking whether your own logger messages are appearing at the expected level

4.9 PROFILER

Best for:

  • frame budget overview
  • top hot tasks
  • top hot FSMs
  • GC and thread-pool diagnostics
  • seeing whether the cost is task-side, FSM-side, or memory-side

Think of PROFILER as the aggregation layer over TASKS, FSM, and network telemetry.


5. Console commands

The built-in command registry currently includes the following commands.

Command What it does
help list commands
clear clear console output
echo <message> echo text back
version show ServiceManager version
`mode [client server]`
`tasks [list info
`fsm [list info
`entities [list info ]`
network summary of network activity
ds summary of persistent entities
perf print memory/FPS/budget metrics
switch <subsystem> jump to another subsystem

Example console session

> mode server
Switched to server mode

> tasks list
Scheduled Tasks:
  ● GlobalStateMachineHeartbeat active (×128)
  ○ ServiceManagerBrainTick idle (×64)

> fsm info TrafficLight_Demo
FSM: TrafficLightFSM
  State: Yellow
  Active: true
  Priority: 1
  Duration: 1.42s
  Transitions: 23

> perf
Performance Metrics:
  Memory: 118.24 MB
  FPS: 60.0
  Budget: 15.00ms

Console tips

  • use mode server before inspecting authoritative data
  • use tasks info GlobalStateMachineHeartbeat when FSMs appear frozen
  • use fsm cancel <id> as a safe recovery tool in development
  • use switch profiler when you discover a hot task or hot FSM and want the bigger picture

6. Debug attributes and telemetry worth knowing

6.1 FSM fields

The current FSM implementation exposes or maintains:

  • State
  • _activeStateName
  • StateDuration
  • TotalDuration
  • TransitionCount
  • TransitionHistory
  • Perf
  • IsActive

TransitionHistory entries can include:

  • From
  • To
  • Time
  • Args
  • WaitSpan
  • ContextSnapshot
  • TransitionId

That makes it much easier to answer:

“What state was this machine in, with what context, when it transitioned?”

6.2 Entity fields

The current entity implementation tracks:

  • Version
  • _versionHistory
  • Pending
  • _pendingKeys
  • Data
  • Schema
  • Context
  • IsValid

_versionHistory is especially valuable when debugging rapid state changes or nil-cleared fields.

6.3 Scheduler fields

Useful scheduler diagnostics include:

  • Tasks
  • _running
  • LastFrameStats
  • TaskStats
  • PerformanceManager:GetStatsSnapshot()
  • GetThreadPoolStats()

6.4 Logger history

Logger keeps a 500-entry circular buffer. Use it when Studio output has already scrolled past the useful event.


7. Logging strategy that actually helps

The current Logger supports:

  • ERROR
  • WARN
  • INFO
  • DEBUG

with the current level weights:

  • ERROR = 1
  • WARN = 2
  • INFO = 3
  • DEBUG = 4

and prints only when the message level is less than or equal to Settings.Logger.MinimumLoggingLevel.

Recommended development settings

Logger = {
    DebuggingEnabled = true,
    MinimumLoggingLevel = 4,
}

Recommended staging / production trend

  • keep framework ERROR and WARN visible
  • lower noisy DEBUG logs unless you are profiling something specific
  • attach your own failure handlers to FSM lifecycle signals for domain-level alerts

Useful log placement

Put logs at:

  • state entry for important workflow checkpoints
  • failure boundaries
  • remote validation rejects
  • persistence failures
  • unexpected nil/resource-missing situations

Do not spam OnHeartbeat() with per-frame logs unless you are doing a short targeted trace.


8. Common problems and how to debug them

8.1 “My FSM never enters the next state”

Check, in order:

  1. is the FSM present in the FSM tab?
  2. is GlobalStateMachineHeartbeat present in TASKS?
  3. is the machine in the correct context (client vs server)?
  4. is the transition legal according to validOutcomes?
  5. did ScheduleTransition() or Timeout actually get set?
  6. is there an error in OnLeave / OnEnter / OnHeartbeat?

Use:

fsm info <id>
tasks info GlobalStateMachineHeartbeat

8.2 “UpdateEntity() returns false”

The current BaseEntity:UpdateEntity() fast-fails when:

  • the entity is destroyed
  • the entity is locked by another caller
  • there are no pending changes
  • the entity is immutable (Mutable ~= true)

Inspect the entity in the ENTITY tab and verify the definition itself.

8.3 “The client did not reflect the server change”

Check:

  • is the field marked Replicate = true?
  • did the server actually commit the entity with UpdateEntity()?
  • does NETWORK show the update event?
  • did the client receive a newer _v?
  • is ApplyChanges() handling the field?

8.4 “The dashboard looks empty”

Usually one of three things:

  • you forgot StartServiceManager() on the client
  • you are in the wrong context
  • boot failed before subsystems had real data to fetch

8.5 “The profiler shows spikes but I cannot tell why”

Use this pairing:

  • PROFILER to identify the spike class
  • TASKS for task-level detail
  • FSM for machine-level detail
  • INSIGHTS for rule-based anomaly hints

8.6 “Remote payloads look truncated”

That is often intentional sanitization. Inspect the detailed network drill-down and remember that deep payloads are bounded to keep the dashboard stable.

8.7 “Server mode keeps disconnecting”

Watch the status bar and the console. The client marks nexus.connected = false when ServiceManager_ServerSnapshot polls fail.


9. Advanced debugging hooks

ServiceManager also ships with a Studio/test-oriented debug bridge via ReplicatedStorage attributes.

Commands written to ReplicatedStorage:SetAttribute("ServiceManagerCmd", ...) can drive actions such as:

  • context:server
  • subsystem:FSM
  • fsmDetail:<id>
  • fsmViz:<id>
  • netDetail:<name>
  • consolePush:<message>

This exists primarily for integration tests and command-bar debugging, but it is useful to know when you need to automate UI inspection.


10. A repeatable debugging checklist

Before editing code, check:

  • correct runtime context selected
  • GlobalStateMachineHeartbeat exists
  • entity and FSM IDs exist as expected
  • replicated field is actually marked Replicate = true
  • Mutable = true on any entity that commits
  • TransitionHistory or _versionHistory show the expected event
  • profiler data confirms where the cost lives
  • console command output agrees with the visual tabs

Related guides

Clone this wiki locally