# Error output When a runtime error occurs, the VM prints its state at the time it stopped. The output includes: 1. The instruction pointer; 2. The data stack; 3. The environment stack; 4. The call stack. ## Instruction pointer (IP) The instruction pointer is useful for debugging alongside the program's opcode listing. Run the VM with the `--debug` (`-d`) flag and the path to a compiled program to print its opcodes without running it. The output looks roughly like this: ``` 0000: MK_ENVTABLE 0001: JMP IP: 53 0003: MK_ENVTABLE 0004: LOADCONST #0 ('a') 0006: STORE 0007: LOADCONST #0 ('a') 0009: WRITE 0010: MK_ENVTABLE 0011: LOADCONST #0 ('a') 0013: LOOKUP_ENV 0014: GET_FIELD #0 ... ``` The instruction index helps you find the instruction where the exception occurred. See the [opcode reference](../internals/opcodes.md) for the complete list and descriptions. ## Data stack The data stack is printed as a list of values in the form `[T] V`, where `T` is the type number and `V` is the value. Strings and objects are prefixed with `str: V` and `ref: V`, respectively. Example: ``` > Data stack: > [2] str: 'this' ``` Values are printed from top to bottom, so the most recent values appear first. ## Environment stack The environment stack is printed as two lists: objects owned by the environment and names local to it. Example environment: ``` > Environments: > [1] 0x55a9d8196a20: > Owned objects (0/2): > Local entries (3/4): > [14] b = 4 > [1] a = ref 0x55a9d81969e0 > [0] this = 0 > [0] 0x55a9d8196930: > Owned objects (1/2): > ref: 0x55a9d81969e0 (entries: 1) > Local entries (1/2): > [1] sum = ref 0x55a9d81969e0 ``` `> [N] A` identifies the environment table itself. `N` is the table's nesting level (larger values mean a deeper environment), and `A` is its memory address. The first list is `Owned objects`; it shows the number of elements and the allocated array size as `(/)`. Objects are listed as `ref: A (entries: N)`, where `A` is the object's memory address and `N` is the number of fields it contains. The second list is `Local entries`, with the number of entries and allocated capacity. Each entry has the form `[T] N = V`, where `T` is the type number, `N` is the entry name, and `V` is its value. ## Call stack The call stack contains return addresses. An address is pushed when the `CALL` opcode runs and popped by `RET`. ``` > Call stack: > [0] 53 ``` Each entry has the form `[L] IP`, where `L` is the nesting level (larger means deeper) and `IP` is the instruction index to jump to after returning. ## Complete output A complete error report looks like this: ``` ===== ERROR ===== > Caused on IP: 21 > Data stack: > [2] str: 'this' > Environments: > [1] 0x55a9d8196a20: > Owned objects (0/2): > Local entries (3/4): > [14] b = 4 > [1] a = ref 0x55a9d81969e0 > [0] this = 0 > [0] 0x55a9d8196930: > Owned objects (1/2): > ref: 0x55a9d81969e0 (entries: 1) > Local entries (1/2): > [1] sum = ref 0x55a9d81969e0 > Call stack: > [0] 53 Error: runtime error - expected 2 values in data stack ```