Skip to main content

Debugging

Tips for debugging your mods during development.

Hot Reload

The fastest way to test changes is hot reloading. After rebuilding your mod:

  • Press Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac) in-game
  • This calls api.reloadMods() internally, which clears all mod callbacks, UI components, custom layers, and custom train types, then re-executes all mod scripts

If you're using pnpm dev, Vite automatically rebuilds on file save, so you just need to press the reload shortcut in-game.

note

Hot reload clears most mod state, but some things persist (like already-built tracks and stations). If your mod gets into a weird state, restarting the game fully is the safest reset.

Console Logging

Use console.log with a tag prefix to identify your mod's output:

const TAG = '[MyMod]';
console.log(`${TAG} Initialized`);
console.warn(`${TAG} Something unexpected`, someData);
console.error(`${TAG} Failed to load`, error);

Viewing Logs

In-game: Open the developer console with Ctrl+Shift+I (Windows/Linux) or Cmd+Option+I (Mac).

With pnpm dev: Logs are printed to your terminal and saved to debug/latest.log. The game launcher enables Electron logging automatically.

Error Handling

Wrap your initialization in try/catch to avoid crashing the game:

api.hooks.onMapReady((_map) => {
if (initialized) return;
initialized = true;

try {
// Setup code
console.log(`${TAG} Initialized successfully.`);
} catch (err) {
console.error(`${TAG} Failed to initialize:`, err);
api.ui.showNotification('My Mod failed to load. Check console.', 'error');
}
});

For hooks that run repeatedly, consider wrapping each callback:

api.hooks.onDayChange((day) => {
try {
// Your logic
} catch (err) {
console.error(`${TAG} Error on day ${day}:`, err);
}
});

Game Error Hooks

The API provides hooks for catching game-level warnings and errors:

api.hooks.onWarning((message) => {
console.warn(`${TAG} Game warning:`, message);
});

api.hooks.onError((error) => {
console.error(`${TAG} Game error:`, error);
});

Type Checking

Run TypeScript's type checker to catch errors before building:

pnpm typecheck

This runs tsc --noEmit and reports any type errors without producing output files. It's a good practice to run this before testing in-game.

Common Issues

"SubwayBuilderAPI Not Found"

Your mod script ran before the game initialized the API. This shouldn't happen with the template's structure, but if it does:

  • Make sure main in manifest.json is "index.js"
  • Make sure you're checking if (!api) before using the API

UI Not Showing Up

  • Check that you're registering UI inside onMapReady — the UI system isn't ready before the map loads
  • Verify your component doesn't throw during render (check console for React errors)
  • Make sure the id you're using is unique — duplicate IDs silently fail

Changes Not Appearing After Reload

  • Verify Vite rebuilt successfully (check terminal for build errors)
  • Make sure the symlink is still intact (pnpm dev:link)
  • Try a full game restart if hot reload isn't picking up changes

React Hooks Errors ("Invalid Hook Call")

This usually means there are multiple React instances. Make sure:

  • You're importing from 'react' (not installing react as a dependency)
  • The Vite alias in vite.config.ts is correctly pointing to src/types/react.ts
  • You haven't accidentally installed react in node_modules

On Windows, creating symlinks may require Administrator privileges. Either:

  • Run your terminal as Administrator
  • Enable Developer Mode in Windows Settings (Settings > For Developers > Developer Mode)