Send Feedback
Skip to content

Debug q Code

Configure your environment for interactive debugging, inspect the stack to diagnose runtime errors, and implement programmatic traps for production.

Overview

Prepare the environment

Configure your session to handle errors interactively by setting the error mode to Suspend (Mode 1) using \e. This stops execution at the error so you can inspect the state.

Prerequisites

Use v4.0+ (check .z.K) for advanced features like & (frame info) and .Q.sbt.

q)// Check version
q)if[4.0>.z.K;-2 "Warning: KDB-X 4.0+ recommended for full debug functionality"];
q)// Set error mode to Suspend
q)\e 1
Available error modes

KDB-X supports three error modes. The effective default depends on the execution context (see Error trap modes).

Command Mode Behavior Use Case
\e 0 Abort Clears stack and returns error. IPC / Sync messages (Default override)
\e 1 Suspend Enters interactive debugger. Console / Development (Default override)
\e 2 Dump Prints stack trace and aborts. Headless / Production

Trigger and interpret errors

With your environment configured, test your setup by generating a controlled error to see the debugger in action.

q)calculate:{x+10}
q)process:{calculate x}
q)main:{process x}
q)
q)// Trigger a Type Error to enter suspension
q)main `type_error
'type
  [3]  calculate:{x+10}
                   ^
q))
Visual Guide: Interpreting the suspension

When the debugger suspends, check for these signs:

  • Suspension depth: The prompt adds ) (for example, q))). Each ) represents one level
  • Error marker: A caret ^ points to the failed primitive
  • Frame index: Bracketed numbers (for example, [0]) show the stack frame

Once execution is suspended, use the debugger to inspect the application state and check variable values at the time of the error.

Reference: Debugger commands

Inspection

Command Description
.Q.bt[] Print the full backtrace. >> marks the current frame.
& Print local variables in the current frame (v4.0+).
.z.ex Return the failed primitive.
.z.ey Return the arguments passed to the failed function.

Navigation

Key Action
` Move up to an older (parent) frame.
. Move down to a newer (child) frame.
q))// Inspect the error context
q)).z.ex   / View failed primitive
+
q)).z.ey   / View arguments
`type_error
10
q)).Q.bt[] / Print backtrace
  [3]  calculate:{x+10}
                   ^
  [2]  process:{calculate x}
                ^
  [1]  main:{process x}
             ^
>>[0]  main `type_error
       ^

Resolve the suspension

After identifying the root cause, decide whether to fix the issue to resume execution or to abort the process entirely.

q)):20  / Resume and return 20 
q)):    / Resume and return generic null (::)
q))\    / Abort execution and clear the stack
Nested debugging

If you are in a nested debug session (for example, q)))), \ pops only one level. Repeat until you reach the root prompt q).

Implement programmatic traps

While interactive debugging is ideal for development, production environments require a different approach. Since you cannot stop execution in production, use .Q.trp and .Q.sbt to log stack traces automatically.

Handler arguments

  • err: The error string
  • bt: The backtrace object
safeRun:{[f;x]
  .Q.trp[f;x;{[err;bt]
    -2"Captured Runtime Error: ",err;
    -2"Stack Trace:";
    -2 .Q.sbt bt;}]};

// Execute with trap
safeRun[{x+`a};1]
Captured Runtime Error: type
Stack Trace:
  [3]  {x+`a}
         ^
  [2]  (.Q.trp)

  [1]  safeRun:{[f;x].Q.trp[f;x;{[err;bt] -2"Captured Runtime Error: ",err;-2"Stack Trace:";-2 .Q.sbt bt;}]}
                     ^
  [0]  safeRun[{x+`a};1]
       ^

Parse errors

Errors thrown by parse also appear in .Q.trp with location information, essentially treating syntax errors in dynamic code as runtime errors.

Configure remote debugging

You may need to debug across network boundaries. To capture remote stack traces, wrap the request handler .z.pg. This returns the backtrace to the client for diagnosis.

Server setup

Start the server process (for example, on port 5001) and define the request handler to capture stack traces.

/ Start server on port 5001
\p 5001

/ Define .z.pg to return (0;result) or (1;backtrace)
.z.pg:{[x]
  .Q.trp[
    {(0;value x)};                                     / Try: Execute request
    x;                                                 / Arg: Incoming query
    {[err;bt] (1;"Remote Error: ",err,"\n",.Q.sbt bt)} / Catch: Return (1; Error Log)
  ]
 }

/ Define a function that will fail
f:{{x*y}[x;3#x]}
Protocol details

This example uses a simple list protocol to distinguish success from failure:

  • Success: (0; result)
  • Failure: (1; backtrace)

The client checks the first element to determine how to handle the response.

Client session

Connect to the server and handle the response protocol.

q)// Connect to remote
q)h:hopen 5001
q)// Execute a query that signals an error
q)r:h"f `a"
q)// The first element indicates failure (1)
q)r 0
1
q)// The second element contains the formatted backtrace
Remote Error: type
  [5]  f@:{x*y}
            ^
  [4]  f:{{x*y}[x;3#x]}
          ^
  [3]  f `a
       ^
  [2]  .z.pg@:{(0;value x)}
                  ^
  [1]  (.Q.trp)

  [0]  .z.pg:{[x].Q.trp[{(0;value x)};x;{[err;bt] (1;"Remote Error: ",err,"\n",.Q.sbt bt)}]}
                 ^

Client-side handling

Check the response format on the client. If the first element is 1, print the backtrace from the second element.