> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.refineryteam.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Crash Reporting

> Pattern-matched exception reports with human-readable help lines, logged cleanly and saved to disk.

`xyz.refineryteam.refinerycore.api.crash` turns raw stack traces into actionable reports. A `CrashHandler` matches thrown exceptions against registered `CrashHint`s — each hint recognizes a class of failure and carries a headline, extracted context fields, and human guidance lines ("what you can try") printed alongside the stack trace.

Plugins extending [`RefineryPlugin`](/refinerycore/installation#refineryplugin) receive a handler from `onLoad()` through `getCrashHandler()`. `RefineryCorePlugin` uses that handler for failed startup steps and configuration reloads, and registers default hints for database, I/O, missing-class, API mismatch, illegal-state, and null-pointer failures.

<Note>
  Every report line goes through the plugin's `Logger` rather than raw stdout, so timestamps, thread names, and log levels stay intact — the report reads like any other server log output instead of an interleaved block.
</Note>

## Basic usage

```java MyPlugin.java icon="java" theme={"system"}
CrashHandler crashes = CrashHandler.of(this);

crashes.hint(CrashHint.of()
    .matchesType(java.sql.SQLException.class)
    .title("Database error")
    .context("SQL State", e -> e instanceof java.sql.SQLException sql ? sql.getSQLState() : null)
    .help(
        "1. Is the database reachable from this machine?",
        "2. Check database.username / database.password in config.yml.",
        "3. If using SQLite, verify the data folder is writable."
    )
    .build());

try {
    riskyDatabaseOperation();
} catch (Exception e) {
    crashes.report(e, "while saving player data");
}
```

A matching report prints a boxed headline, the exception message and root cause, any extracted context fields, the hint's help bullets, and the full stack trace with causes. Reports are also appended to `logs/refinery-crash-reports.txt` for post-mortem reading, since console spam scrolls away.

## `CrashHint`

Each hint is built fluently:

| Builder method                                     | Description                                                                                                                                                     |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `matches(Predicate<Throwable>)`                    | Predicate deciding whether the hint applies — tested against the **root cause** of the reported exception                                                       |
| `matchesType(Class<? extends Throwable>)`          | Convenience: match by exact class or subclass                                                                                                                   |
| `title(String)`                                    | Headline shown at the top of the report box                                                                                                                     |
| `context(String key, Function<Throwable, String>)` | Extracts a contextual value from the throwable (e.g. SQL state, failing host); rendered as `key: value` lines. Failing extractors never break report generation |
| `help(String... lines)`                            | Human guidance lines rendered under "What you can try" when the hint matches                                                                                    |
| `build()`                                          | Returns the finished hint                                                                                                                                       |

Register more specific hints before general ones — the **first matching hint wins**, and a report without any matching hint falls back to a generic `"Unhandled exception"` headline.

## `CrashHandler`

| Method                                                  | Description                                                                                                                                                     |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CrashHandler.of(plugin)`                               | Creates a handler bound to your plugin's logger and data folder                                                                                                 |
| `hint(CrashHint)`                                       | Registers a hint; returns the handler for chaining                                                                                                              |
| `report(Throwable)` / `report(Throwable, String where)` | Reports an exception, optionally with a short description of what was happening (e.g. `"while running riskyOperation"`). `null` throwables are silently ignored |
| `withoutFileLogging()`                                  | Disables writing to `logs/refinery-crash-reports.txt`; reports only go to the console log                                                                       |

<Note>
  Wrap `report(...)` calls around the operations most likely to fail at runtime — database access, web requests, file I/O. Since hints carry the troubleshooting steps, this is also a good place to encode knowledge that currently lives in your head or your support Discord.
</Note>
