Skip to content

Runtime limitations

TypeScript is the source language, but generated code runs inside KILLSCRIPT’s restricted XLua environment with Lua 5.4 semantics. It is not Node.js, a browser, Roblox Luau or unrestricted desktop Lua.

The compiler rejects patterns that would emit globals the game does not expose. This turns a late Lua failure into an earlier build error.

Do not rely onWhyUse instead
try/catch, throw, runtime typeofRequire unavailable pcall, error or typeValidate inputs and branch explicitly
async, await, generatorsRequire unsupported coroutine/runtime helpersScheduler callbacks
dynamic import() or direct require()The game loader does not resolve project paths reliablyStatic relative imports bundled by the compiler
runtime npm importsArbitrary package runtimes are not bundled safelyPut implementation helpers in src/
browser/Node globalsThey do not exist in XLuaThe typed game API or compile-time packages
passing or destructuring SDK compiler handlesLowering requires a direct, statically known use siteImport the handle, then call its property or method directly
client Scheduler.OnTickNot exposed in client contextscheduler.frame() or a time/tick guard
server Scheduler.OnFrameReflex has no render framesscheduler.tick()

Type-only npm packages are safe because they disappear. SDK imports are also safe: compiler macros are replaced and only the necessary generated helpers remain.

Static multi-file architecture is supported

Section titled “Static multi-file architecture is supported”

Organize code normally:

src/client/main.ts
import "./features/status-hud";
import "./features/world-marker";

Use extensionless relative imports. Every reachable file is bundled into scripts/main.lua or scripts/server.lua, so the game never needs to resolve features/status-hud itself.

Only reachable files are included. A runtime package import outside src/ is rejected unless it is type-only or an SDK compiler import.

Ordinary TypeScript arrays are supported. reduce() and reduceRight() need an explicit initial value:

const total = values.reduce((sum, value) => sum + value, 0);

Native LuaArray userdata is indexed from one and must use Game array helpers or an explicit 1..Length loop.

These calls are typed because they exist, but their current runtime behavior is not reliable:

  • several raw Network.SendTable calls during one tick collapse to one; use defineNetwork() for ordered batching;
  • InputAction.Disable() changes IsPressed() but may not suppress an existing OnPerformed callback; guard the callback with your own state;
  • Reflex AgentInput.SetButtonState, SetLookRotation and SetMoveDirection return successfully but do not affect the actually controlled player;
  • the module settings UI may temporarily stop displaying default bindings after an action-map refresh even though those bindings still work.

The game-specific issues above have been reported to the developer. They are documented here temporarily so code and AI assistants do not infer working behavior from a successful call alone.

When a build fails, read the first compiler diagnostic and use Troubleshooting for common project and sync problems.