Skip to main content
The wtf command displays the backtrace of the last uncaught exception. The name stands for “What The Failure” (or, you know, the other thing). The more question marks or exclamation points you add, the more stack trace lines are shown.

Syntax

wtf [?!?!...] [options]

Aliases

  • last-exception
  • wtf?

Arguments

incredulity
string
A string of question marks (?) and/or exclamation points (!). The longer the string, the more backtrace lines are shown.
  • No argument: Shows 8 lines (default)
  • ?: Shows 16 lines
  • ??: Shows 32 lines
  • ???: Shows 64 lines
  • Each additional character doubles the count

Options

--all
flag
Alias: -aShow the entire backtrace without truncation
--grep
pattern
Filter backtrace lines by pattern (supports regular expressions)
--insensitive
flag
Alias: -iMake grep search case-insensitive
--invert
flag
Alias: -vInvert grep match (show lines that don’t match)

Usage Examples

Basic Exception Trace

>>> throw new Exception('Something went wrong');
Exception with message 'Something went wrong'

>>> wtf
Exception with message 'Something went wrong'
--
 0: {main}()
 1: Psy\Shell->execute()
 2: Psy\ExecutionLoop\Loop->run()  
 3: eval()
 4: throw new Exception('Something went wrong')

Show More Lines

Add question marks or exclamation points for more detail:
>>> wtf ?
>>> wtf ??
>>> wtf ????  
>>> wtf ?!?!?!?
Each ? or ! doubles the number of lines shown:
  • wtf → 8 lines
  • wtf ? → 16 lines
  • wtf ?? → 32 lines
  • wtf ??? → 64 lines
  • etc.
>>> wtf ???
Exception with message 'Database connection failed'
--
  0: {main}()
  1: require('/app/index.php')
  2: App\Bootstrap::init()
  3: App\Database::connect()
  4: PDO->__construct()
  ... (64 lines of backtrace)

Show Complete Trace

>>> wtf -a
>>> wtf --all
Shows every single line of the backtrace without truncation.

Show Nested Exceptions

If exceptions have previous exceptions, wtf shows all of them:
>>> try {
...     throw new RuntimeException('Inner error');
... } catch (Exception $e) {
...     throw new Exception('Outer error', 0, $e);
... }
Exception with message 'Outer error'

>>> wtf
Exception with message 'Outer error'
--
 0: {main}()
 1: throw new Exception('Outer error')

RuntimeException with message 'Inner error'  
--
 0: {main}()
 1: throw new RuntimeException('Inner error')
Each exception in the chain is displayed separately.

Filter Backtrace

>>> wtf --grep /App\\/
>>> wtf --grep /Database/ -i
Shows only backtrace lines matching the pattern.

Real-World Example

>>> $pdo = new PDO('invalid:dsn');
PDOException with message 'could not find driver'

>>> wtf
PDOException with message 'could not find driver'
--
  0: PDO->__construct('invalid:dsn')
  1: eval()
  2: Psy\Shell->execute()

>>> wtf ??
PDOException with message 'could not find driver'
--
  0: {main}()
  1: require('/app/index.php')  
  2: Psy\Shell::debug()
  3: Psy\Shell->__construct()
  4: Psy\Shell->run()
  5: Psy\ExecutionLoop\Loop->run()
  ... (32 lines total)

Line Count Logic

The number of lines shown is calculated as:
lines = max(3, 2^(incredulity_length + 1))
  • wtf (length 0) → 2^1 = 2, but minimum is 3, so 8 lines
  • wtf ? (length 1) → 2^2 = 416 lines
  • wtf ?? (length 2) → 2^3 = 832 lines
  • wtf ??? (length 3) → 2^4 = 1664 lines
If the trace is only slightly longer than the limit, wtf will show the entire trace. For example, if the trace has 35 lines and you request 32, all 35 will be shown to avoid hiding just a few lines.

Smart Truncation

When the trace is truncated, you’ll see a helpful message:
>>> wtf
... (trace shown)

Use wtf -a to see 45 more lines
This reminds you how to see the full trace.

Backtrace Format

Each line shows:
  • Line number - Position in the stack
  • Class/Function - What was being called
  • File and line - Where it was called from (when available)
  5: App\UserController->store()
     at /app/src/Controllers/UserController.php:42
  6: Illuminate\Routing\Controller->callAction()
     at /vendor/laravel/framework/src/Routing/Controller.php:54  

Combine with Other Commands

View Exception Context

>>> someCode()  // Exception!
>>> wtf         // See where it happened
>>> show --ex   // View the source code at that location
>>> wtf         // See the backtrace
>>> show --ex 1 // View line where exception was thrown
>>> show --ex 3 // View the caller  
>>> show --ex 5 // View higher up the stack

Filter and Inspect

>>> wtf --grep /MyApp/  // Find relevant trace lines
>>> show --ex 4         // Inspect that specific level

Common Patterns

Quick Debug

>>> someFunction()  
Exception!
>>> wtf             // What happened?
>>> wtf ??          // Need more context
>>> show --ex       // Let me see the code

Deep Investigation

>>> wtf -a                      // Full trace
>>> wtf --grep /Controller/     // Focus on controllers  
>>> show --ex 5                 // Examine specific level

Compare Exceptions

>>> firstAttempt()
Exception A
>>> wtf --grep /Database/

>>> secondAttempt()  
Exception B
>>> wtf --grep /Database/

Tips

Express your frustration through syntax:
>>> wtf?!?!?!?!?!
The more incredulous you are, the more information you get!
Combine with show --ex for a complete debugging workflow:
>>> wtf        # Overview of what happened
>>> show --ex  # Source code where it happened
Use grep to focus on your code:
>>> wtf --grep "/^(?!Psy|Symfony|Illuminate)/"
Filters out framework noise and shows only your application’s trace.
Only the last exception is shown. If you catch and handle an exception, it won’t appear in wtf:
>>> try { throw new Exception('Caught'); } catch (Exception $e) {}
>>> wtf  # Shows nothing - exception was caught

See Also

  • trace - Show the current call stack
  • show —ex - View exception source code
  • whereami - Show where you are in code

Build docs developers (and LLMs) love