W3docs

getTraceAsString()

Learn the PHP getTraceAsString() method: how it returns an exception's stack trace as a string, how to read the output, and how to log or display it.

What getTraceAsString() Does

getTraceAsString() is a method available on every PHP exception (any class that implements ThrowableException, Error, and their subclasses). It returns the stack trace — the chain of function and method calls that were active at the moment the exception was thrown — formatted as a single human-readable string.

The stack trace answers the question "how did execution get here?" When something throws deep inside your code, the message alone (getMessage()) tells you what went wrong, but the trace tells you the exact path of calls that led to it. That makes it the single most useful piece of information when debugging an error you can't easily reproduce.

getTraceAsString() is the string version of getTrace(), which returns the same information as a structured array. Use getTrace() when you need to inspect individual frames programmatically; use getTraceAsString() when you just want something to log or print.

Syntax

public Throwable::getTraceAsString(): string

It takes no arguments and is final on the base Exception and Error classes, so it always returns PHP's standard trace format. You call it on a caught exception object inside a catch block:

<?php

try {
    // Code that may throw an exception
} catch (Throwable $e) {
    $trace = $e->getTraceAsString();
}

Catching Throwable (rather than only Exception) means you also handle Error objects such as TypeError and DivisionByZeroError. See the Exception chapter for the full hierarchy.

A Complete, Runnable Example

This script throws an exception two levels deep so you can see what the trace string actually looks like:

<?php

function loadUser(int $id): array
{
    throw new InvalidArgumentException("No user with id $id");
}

function handleRequest(): void
{
    loadUser(42);
}

try {
    handleRequest();
} catch (Throwable $e) {
    echo $e->getTraceAsString();
}

Output:

#0 /app/index.php(10): loadUser(42)
#1 /app/index.php(14): handleRequest()
#2 {main}

Reading the Output

Each line is one frame in the call stack, listed innermost first:

  • #0, #1, … — the frame number. #0 is the call that was running when the exception was thrown; higher numbers are the callers above it.
  • /app/index.php(10) — the file and line number of the call site.
  • loadUser(42) — the function or method that was called, with its arguments. Long string arguments are truncated (e.g. '/etc/app/missin...') to keep the trace readable.
  • #2 {main} — the special final frame marking the top-level script (the global scope).

The throw site itself (the exact file and line where throw ran) is not in this string — it lives in getFile() and getLine().

Examples

Example 1: Logging the Trace to a File

In production you rarely want to show a trace to the user — you log it for later analysis. Combine the message, file, and line with the trace for a complete record:

<?php

try {
    // Code that may throw an exception
} catch (Throwable $e) {
    $entry = sprintf(
        "[%s] %s in %s:%d\n%s\n\n",
        date('Y-m-d H:i:s'),
        $e->getMessage(),
        $e->getFile(),
        $e->getLine(),
        $e->getTraceAsString()
    );

    file_put_contents('/path/to/app.log', $entry, FILE_APPEND | LOCK_EX);
}

LOCK_EX prevents two simultaneous requests from interleaving their log entries. For real applications a logging library such as Monolog is preferable, but the underlying data is the same string you get here.

Example 2: Displaying the Trace in the Browser (Development Only)

When working locally it can be handy to print the trace straight to the page. Wrap it in <pre> so the line breaks are preserved, and escape it so trace contents can't inject HTML:

<?php

try {
    // Code that may throw an exception
} catch (Throwable $e) {
    echo '<pre>' . htmlspecialchars($e->getTraceAsString()) . '</pre>';
}

Never expose traces to end users in production — they reveal file paths, code structure, and sometimes argument values that help attackers. Gate this behind an environment check.

Example 3: Preserving the Trace Across Re-throws

When you catch a low-level exception and re-throw a more meaningful one, pass the original as the previous exception so its trace isn't lost:

<?php

try {
    // some database call that throws PDOException
} catch (PDOException $e) {
    throw new RuntimeException('Could not load the report', 0, $e);
}

The new RuntimeException has its own trace, while getPrevious() gives you back the original exception (and its getTraceAsString()). PHP's default uncaught-exception handler prints both, chained.

Common Gotchas

  • The trace describes the throw point, not the catch point. It is fixed at the moment the exception is constructed, so calling getTraceAsString() later still shows where the exception originated, not where you handled it.
  • Arguments may be truncated or hidden. Long strings are shortened; with the zend.exception_ignore_args INI setting enabled (the default in many production setups), argument values are omitted entirely for security.
  • It returns a string, never null. Even for an exception thrown at the top level you get at least the #0 {main} frame.

Conclusion

getTraceAsString() turns an exception's call stack into a compact, loggable string, making it one of the most valuable tools for diagnosing errors in PHP. Pair it with getMessage(), getFile(), and getLine() to capture a full picture of every failure, log it rather than showing it to users in production, and preserve the chain with getPrevious() whenever you re-throw.

Practice

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