W3docs

debug_backtrace()

Debugging is an essential aspect of programming, and PHP is no exception. In this guide, we'll walk you through the fundamentals of error debugging in PHP.

When a bug appears deep inside nested function calls, the error message alone rarely tells you how the code got there. The debug_backtrace() function answers that question: it returns a snapshot of the call stack at the exact point where you call it, so you can see which function called which, in what file, and on what line. This page explains the function's signature, the shape of the array it returns, practical patterns for using it, and how it fits alongside PHP's error-reporting tools.

What debug_backtrace() returns

debug_backtrace() returns an array of associative arrays — one element per stack frame, ordered from the innermost call (where you invoked it) outward to the script's entry point. It never throws and never stops execution; it just reports the current stack.

The signature is:

debug_backtrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0): array

Parameters

  • $options (int) — a bitmask controlling what each frame includes:
    • DEBUG_BACKTRACE_PROVIDE_OBJECT (default) — include the actual object for method calls.
    • DEBUG_BACKTRACE_IGNORE_ARGS — omit the args index, which keeps the output small and avoids holding references to large arguments.
  • $limit (int) — the maximum number of frames to return. 0 (the default) means the entire stack. Useful when you only need the immediate caller.

Each frame

Each frame is an associative array that may contain:

  • function — the called function or method name.
  • line — the line the call was made from.
  • file — the file the call was made from.
  • class — the class name, for method calls.
  • object — the object instance, when DEBUG_BACKTRACE_PROVIDE_OBJECT is set.
  • type-> for instance calls, :: for static calls, absent for plain functions.
  • args — the arguments passed to the call (unless DEBUG_BACKTRACE_IGNORE_ARGS is used).

Basic example: tracing the call stack

This script walks three nested functions and prints a readable trace from the deepest one:

<?php
function levelThree() {
    $trace = debug_backtrace();
    foreach ($trace as $i => $frame) {
        echo "#$i {$frame['function']}() at line {$frame['line']}\n";
    }
}
function levelTwo() { levelThree(); }
function levelOne() { levelTwo(); }
levelOne();

Output:

#0 levelThree() at line 8
#1 levelTwo() at line 9
#2 levelOne() at line 10

Frame #0 is where debug_backtrace() was called, and each subsequent frame is the caller above it. Use print_r($trace) instead of the loop if you want to see every key (file, args, and so on) at once.

Finding the caller

A common, focused use is figuring out who called the current function — for logging or deprecation warnings. Pass DEBUG_BACKTRACE_IGNORE_ARGS to keep the result light and 2 as the limit, then read frame index 1 (index 0 is the current function):

<?php
function logCaller() {
    $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] ?? null;
    if ($caller) {
        echo "Called by {$caller['function']}() on line {$caller['line']}\n";
    }
}
function doWork() {
    logCaller();
}
doWork();

Output:

Called by doWork() on line 11

The ?? null guard matters when logCaller() is invoked from the top level, where there is no frame 1.

When to use it

  • Logging and diagnostics — attach a trace to a log entry so you can reconstruct how an unexpected state was reached.
  • Deprecation notices — report the exact caller of a function you're phasing out.
  • Custom error handlers — enrich a set_error_handler() callback with the surrounding call stack.
  • Understanding framework flow — see which middleware or hook led into your code.

Gotchas

  • Performance and memory. With the default options each frame keeps args and object references, which can be heavy. In hot paths or when arguments are large, pass DEBUG_BACKTRACE_IGNORE_ARGS.
  • Production code. Treat debug_backtrace() as a debugging tool. Don't leave it printing to output in production — route it to a log instead.
  • Just need a printout? Use debug_print_backtrace(), which echoes a formatted trace directly without returning an array.
  • Inside an exception? The thrown Exception object already carries its trace via $e->getTrace() and $e->getTraceAsString().

PHP error types at a glance

debug_backtrace() is most useful when you already know an error occurred and want context. PHP's errors fall into a few broad categories:

  • Parse (syntax) errors — invalid code the parser rejects before execution, such as a missing semicolon or unmatched brace. These are fatal.
  • Logical errors — the code runs but produces the wrong result; there is no error message, which is exactly when a backtrace helps.
  • Runtime errors — raised while the script runs, ranging from non-fatal notices and warnings (undefined variable, missing include, division warnings) to fatal errors (calling a method on a non-object, exceeding the memory limit) that stop execution.

To control which of these you see, set the level with error_reporting(). During development, enable everything:

<?php
// Report all errors, notices and warnings, and show them
error_reporting(E_ALL);
ini_set('display_errors', '1');
graph TD;
    A[PHP Error] -->|invalid code| B(Parse / Syntax)
    A -->|wrong result| C(Logical)
    A -->|while running| D(Runtime)
    D --> E(Notice / Warning)
    D --> F(Fatal Error)

Practice

Practice
What does the debug_backtrace() function in PHP do?
What does the debug_backtrace() function in PHP do?
Was this page helpful?