PHPackages                             fail-whale/fail-whale - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Debugging &amp; Profiling](/categories/debugging)
4. /
5. fail-whale/fail-whale

ActiveLibrary[Debugging &amp; Profiling](/categories/debugging)

fail-whale/fail-whale
=====================

A robust error handler and pretty printer for PHP

0.1.1(9y ago)325.7k↓35.2%1MITPHP

Since Apr 23Pushed 9y ago1 watchersCompare

[ Source](https://github.com/jesseschalken/fail-whale)[ Packagist](https://packagist.org/packages/fail-whale/fail-whale)[ RSS](/packages/fail-whale-fail-whale/feed)WikiDiscussions master Synced 2d ago

READMEChangelogDependencies (1)Versions (4)Used By (0)

fail-whale
==========

[](#fail-whale)

`fail-whale` is a system for introspecting PHP values and exceptions and rendering them in plain text and interactive HTML.

Installation
------------

[](#installation)

Install [the Composer package](https://packagist.org/packages/fail-whale/fail-whale)

Usage
-----

[](#usage)

Example:

```
use FailWhale\Value;

class Foo {
    private $baz = "bar";
    protected $an_int = 967;
    public $an_array = [
        'baz' => [
            8346 => 762.192,
            'key1' => "string with\nnew lines\n\t\tand\r\n\ttabs\nand a CR",
            'key2' => "random bytes \xc4\x08\x12\xb1",
            'key3' => M_PI,
            'key4' => null,
            'key6' => true,
        ]
    ];
    private $bar;

    function __construct() {
        $this->bar = new Bar();
        $baz =& $this->an_array['baz'];
        $baz['recurse'] =& $baz;
        $baz['stream'] = fopen('php://memory', 'wb');
    }
}

class Bar {
    private $copies;
    function __construct() {
        $this->copies = [$this, $this];
    }
}

print Value::introspect(new Foo)->toString();
```

```
new Foo {
    private $baz = "bar";
    protected $an_int = 967;
    public $an_array = array(
        "baz" => &array002 array(
            8346 => 762.192,
            "key1" => "string with
new lines
		and\r
	tabs
and a CR",
            "key2" => "random bytes \xc4\x08\x12\xb1",
            "key3" => 3.1415926535898,
            "key4" => null,
            "key6" => true,
            "recurse" => *array002,
            "stream" => stream,
        ),
    );
    private $bar = &object002 new Bar {
        private $copies = array(
            *object002 new Bar,
            *object002 new Bar,
        );
    };
}

```

A `Value` can represent an `Exception` or a single PHP value.

### `Value::introspect()`, `Value::introspectRef()`, `Value::introspectException()`

[](#valueintrospect-valueintrospectref-valueintrospectexception)

`Value::introspect()` and `Value::introspectRef()` will handle arbitrary PHP values, including recursive arrays (eg `$a = [&$a]`) and recursive objects.

`Value::introspectException()` will handle any `Exception` and retrieve:

- it's code, message, file and line
- a full stack trace, including function name, class name, arguments, `$this`, file and line
- the entire global state of the PHP program
    - global variables
    - static class properties
    - static variables
- if it is a `ErrorExceptionWithContext`, the local variables ("context") at the point that the PHP error occurred
- the source code which surrounds the line where the exception was thrown and the surrounding code for each function call on the stack

All `Value::introspect*()` methods optionally accept a `IntrospectionSettings` object.

### `Value::toJSON()`, `Value::fromJSON()`

[](#valuetojson-valuefromjson)

`Value->toJSON()` will return a JSON string suitable for `Value::fromJSON()`.

### `Value::toHTML()`, `Value::toInlineHTML()`

[](#valuetohtml-valuetoinlinehtml)

`Value->toHTML()` will return a full HTML document which represents the value in a browsable, expandable/collapsible form.

`Value->toInlineHTML()` will return HTML suitable for embedding in another HTML document.

### `Value::toString()`

[](#valuetostring)

`Value->toString()` will pretty-print the value as a string. It optionally accepts a `PrettyPrinterSettings` object to control how the value is rendered.

PHP values (and exceptions) containing repeated arrays, objects and strings are handled gracefully, as are recursive arrays and objects.

Scalar values (`int`, `string`, `bool`, `float`, `null`) and non-recursive arrays are rendered as valid PHP code.

Error Handler
-------------

[](#error-handler)

### `ErrorUtil::setExceptionTrace()`, `ExceptionWithTraceObjects`

[](#errorutilsetexceptiontrace-exceptionwithtraceobjects)

In order to see the `$this` object (current object) for each stack frame in an exception, you should overwrite the default trace for an exception with one provided by `debug_backtrace()` using `ErrorUtil::setExceptionTrace()`:

```
use FailWhale\ErrorUtil;

$e = new Exception('oh no!');
ErrorUtil::setExceptionTrace($e, debug_backtrace());
throw $e;
```

It is more convenient to do this in the constructor of your exception:

```
use FailWhale\ErrorUtil;

class BadException {
    function __construct($message) {
        parent::__construct($message);
        ErrorUtil::setExceptionTrace($this, debug_backtrace());
    }
}

throw new BadException('oh no!');
```

Or you could instantiate or extend `ExceptionWithTraceObjects` which will do this for you:

```
use FailWhale\ExceptionWithTraceObjects;

throw new ExceptionWithTraceObjects('oh no!');
```

`ErrorUtil::setExceptionTrace()` uses reflection to set the private property `Exception::$trace`, which is returned by `$e->getTrace()`. Try not to think about that too much. ;)

You can also use `ErrorUtil::setExceptionTrace()` to remove the top stack frame from an exception, to avoid your error handler appearing in the trace, for example.

```
use FailWhale\ErrorUtil;

set_error_handler(function ($type, $message, $file, $line, $context = null) {
    $e = new ErrorException($message, 0, $type, $file, $line);
    ErrorUtil::setExceptionTrace($e, array_slice($e->getTrace(), 1)); // setContext()` with the `$context` array provided to your error handler from `set_error_handler()`. For example:

```
use FailWhale\ErrorExceptionWithContext;

set_error_handler(function ($type, $message, $file, $line, $context = null) {
    $e = new ErrorExceptionWithContext($message, 0, $type, $file, $line);
    $e->setContext($context); // setCode(ErrorUtil::phpErrorConstant($type)); // getMessage();
});
```

Error Handler + Pretty Printer
------------------------------

[](#error-handler--pretty-printer)

Putting these two pieces together, an error handler which prints a interactive HTML version of an exception to the browser might look like this:

```
use FailWhale\ErrorUtil;
use FailWhale\Value;

ErrorUtil::setErrorAndExceptionHandler(function (Exception $e) {
    $value = Value::introspectException($e);

    if (PHP_SAPI === 'cli')
        print $value->toString();
    else
        print $value->toHTML();
});
```

###  Health Score

32

—

LowBetter than 69% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity30

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 99% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~528 days

Total

3

Last Release

3399d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1559204?v=4)[Jesse Schalken](/maintainers/jesseschalken)[@jesseschalken](https://github.com/jesseschalken)

---

Top Contributors

[![jesseschalken](https://avatars.githubusercontent.com/u/1559204?v=4)](https://github.com/jesseschalken "jesseschalken (510 commits)")[![caleshious](https://avatars.githubusercontent.com/u/4555799?v=4)](https://github.com/caleshious "caleshious (2 commits)")[![jeffery](https://avatars.githubusercontent.com/u/175114?v=4)](https://github.com/jeffery "jeffery (1 commits)")[![jeichorn](https://avatars.githubusercontent.com/u/122486?v=4)](https://github.com/jeichorn "jeichorn (1 commits)")[![steveivt](https://avatars.githubusercontent.com/u/10135605?v=4)](https://github.com/steveivt "steveivt (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fail-whale-fail-whale/health.svg)

```
[![Health](https://phpackages.com/badges/fail-whale-fail-whale/health.svg)](https://phpackages.com/packages/fail-whale-fail-whale)
```

###  Alternatives

[fjogeleit/prometheus-messenger-middleware

Prometheus Middleware for the Symfony Messenger Component

2255.2k](/packages/fjogeleit-prometheus-messenger-middleware)[spatie/craft-ray

Easily debug CraftCMS projects

1638.6k](/packages/spatie-craft-ray)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
