# Debugging

**Partly built.** Missing: jadpo incident, trace, traces, metrics, logs, watch, call, test new --from, replay and mcp. See [What is built](/docs/debugging-and-review-built.md).

Jadpo code is written mainly by coding agents and read by people, so two
jobs matter most. When something goes wrong, you or your agent need to get
from the symptom to the `.jadpo` line and the reason, without reading the
code Jadpo generates. And when an agent hands over a large change, you need
to see what it does to your app, such as who can now read which data,
before you read it line by line. This page covers both: where errors
point, how to see what a request did and why, and how to review a change.

The command line, the developer console and the agent tools (MCP) all show
the same evidence. The compiler and the runtime record that evidence, and
each view only displays it. If the console shows why a caller was refused,
that's because the compiler and the runtime recorded the reason, not
because the console worked it out.

| Tool | What it does |
|---|---|
| Errors point at `.jadpo` | Always a `.jadpo` file and line, in development and production |
| Production incidents | `jadpo incident` names the line in the build that failed, then where that code is now |
| Breakpoints | Not offered |
| Why the language decided something | `jadpo why` |
| What a request did | The request timeline in `jadpo dev`; `jadpo trace <request id>` |
| Watching code run | `jadpo watch` waits for a named part of the code to run and prints it |
| Provider calls in development | `jadpo calls`: every call logged with full values, in development only |
| Traces, metrics and logs in development | `jadpo traces`, `jadpo metrics`, `jadpo logs`, with filters, `--follow` and `--json` |
| Failing request to test | `jadpo test new --from <request id>` |
| Run a query or action | `jadpo call <name> --as <user>` |
| Developer console and MCP | A local web page and read-only agent tools over the same evidence |
| Reviewing a change | A report with behaviour first, and a static web view of it |
| JSON for agents | Every command and view ([Tools for agents](/docs/tools-for-agents.md)) |
| Coverage by path | Tests and production compared path by path |
| Production in review | The approval report shows traffic and failures on the paths a change touches |
| Replaying a production request | Opt-in recording of what each effect returned, replayed locally |
| Query cost of a change | Queries added or removed per path, in the approval report |

Most of this isn't built yet; [What is built](/docs/debugging-and-review-built.md) says which
parts are.

### A request in `jadpo dev`

`jadpo dev` runs your app and prints one line for each request, with its
request id, its status and how long it took, so it is where most debugging
starts. Here is a small app with one route, which stores nothing and which
anyone may call:

`domains/todos/routes/todos.jadpo`:

```jadpo
use todos/types { NewTodo, TodoView }
use todos/actions { add_todo }

/// The todo list.
routes Todos {
    prefix: /todos

    /// Adds a todo.
    POST / {
        authentication: RouteAuthentication.none
        input: NewTodo
        output: TodoView
        run: add_todo(input)
    }
}
```

`domains/todos/types/new_todo.jadpo`:

```jadpo
/// What a caller sends to add a todo.
type NewTodo = Input {
    title: Text
}
```

`domains/todos/types/todo_view.jadpo`:

```jadpo
/// A todo, as the app sends it back.
type TodoView = Output {
    title: Text
    done: Bool
}
```

`domains/todos/actions/add_todo.jadpo`:

```jadpo
use todos/types { NewTodo, TodoView }

/// Builds the todo and sends it back. It stores nothing.
action add_todo(input: NewTodo) -> TodoView {
    return TodoView {
        title: input.title
        done: false
    }
}
```

`policy.jadpo`:

```jadpo
use todos

policy {
    actions: {
        todos.add_todo: [Access.public]
    }
}
```

`RouteAuthentication`, `Access`, `Text` and `Bool` are built into Jadpo, and
every other name is declared here. Run `jadpo api update` once, then
`jadpo dev`, and send it two requests:

```sh
curl -X POST http://localhost:3000/todos \
  -H 'content-type: application/json' -d '{"title": "Buy milk"}'
curl -X POST http://localhost:3000/todos \
  -H 'content-type: application/json' -d '{"title": 5}'
```

```text
$ jadpo dev
jadpo dev, started 02:47:52
listening on http://localhost:3000
    routes  2 routes
serving: saves reload, press ctrl-c to quit
req_4035  POST /todos                        200   6 ms   127.0.0.1
req_beb8  POST /todos                        422 invalid_input   0 ms   127.0.0.1
```

The second title isn't text, so the app refused it with a 422 and said why.
Its line shows the start of the request's id, which the caller also has in
the `x-request-id` header and an error's `request_id`, so a report from a
caller leads to the line.

| Page | What it covers |
|---|---|
| [Errors point at the .jadpo line](/docs/errors-point-at-the-jadpo-line.md) | Every stack, log event and error response that names a place names a `.jadpo` file and line, never the generated code. |
| [The request timeline in jadpo dev](/docs/the-request-timeline-in-jadpo-dev.md) | `jadpo dev` records every request it serves and prints one line for each, with its request id. |
| [Watching code run: jadpo watch](/docs/watching-code-run-jadpo-watch.md) ○ not built | Not built yet. |
| [Provider calls in development: jadpo calls](/docs/provider-calls-in-development-jadpo-calls.md) | In `jadpo dev`, every provider operation is faked by default, so nothing leaves your machine and you need no credentials. |
| [Traces, metrics and logs in development](/docs/traces-metrics-and-logs-in-development.md) ○ not built | In development, your app's telemetry, its traces, metrics and logs, stays on your machine (Telemetry). |
| [Capturing a failing request as a test](/docs/capturing-a-failing-request-as-a-test.md) | The quickest reliable fix starts by reproducing the bug. |
| [Running a query or action: jadpo call](/docs/running-a-query-or-action-jadpo-call.md) | Not built yet. |
| [jadpo why: why the language decided something](/docs/explain-a-decision.md) | Much of what surprises people in Jadpo is a decision the language made for them: policy hid a record, a lifecycle filtered it out, a subscriber didn't run, or a cache answered. |
| [Production incidents after the code has changed](/docs/production-incidents-after-the-code-has-changed.md) ○ not built | By the time you look at a production failure, the code may have moved on. |
| [Breakpoints and stepping](/docs/breakpoints-and-stepping.md) | You can't set a breakpoint in a `.jadpo` file or step through one in an editor. |
| [The developer console and MCP](/docs/the-developer-console-and-mcp.md) ○ not built | The same evidence is also there as a web page, and as tools for an agent that can't run commands. |
| [What the graph and production evidence add](/docs/what-the-graph-and-production-evidence-add.md) ○ not built | Each of these joins the compiler's graph to path IDs. |

[What is built](/docs/debugging-and-review-built.md) says which of this works today.
