---
kind: guide
zz: "0.8.0"
updated: 2026-10-10
state: live
rules: https://zriz.io/llms.txt
---
# Test that a bad request returns 400

Send a broken request on purpose in a zriz pipeline. Check for status 400 and the exact error text, so a bad input never gets a 500 or a 201.

## The problem {#problem}

A request with a missing field must get `400` and a clear error. Without a test, a change can turn that result into `500`. Or the API accepts the bad data and stores it.

## The test {#test}

The example is a shop API. `POST /api/auth/register` needs `email`, `password`, and `name`. The test sends no `name`.

Start from a project that `zz init` made: the [quick start](https://zriz.io/docs.md) gives the commands. Add the action `register` to the resource file.

`.zriz/resources/target.json`:

```json
{
  "type": "http",
  "description": "Your app under test",
  "base-url": "${env.TARGET_URL}",
  "headers": { "Content-Type": "application/json" },
  "actions": {
    "check": { "method": "GET", "path": "/api/health" },
    "register": { "method": "POST", "path": "/api/auth/register" }
  }
}
```

`.zriz/pipelines/register-bad-request.json`:

```json
{
  "description": "Sign up with no name: the API must answer 400",
  "steps": [
    { "set": { "email": "u-${gen.uuid}@test.com" } },
    {
      "call": "target/register",
      "body": { "email": "${ctx.email}", "password": "secret123" },
      "expect": [
        ["status", "==", 400],
        ["body.error", "==", "email, password, and name are required"],
        ["body.token", "not-exists"]
      ]
    }
  ]
}
```

## Run it {#run}

```sh
zz run register-bad-request
```

```text
"status":"pass"
```

## What it proves {#proves}

- `status == 400`: the API refuses the request. A `500` means that the input broke the server.
- `body.error == ...`: the client gets the text that tells what is wrong.
- `body.token not-exists`: a refused sign-up gives no token.

> Common mistake: A check of only `status >= 400` passes on a `500`. Compare with the exact code.

## Next {#next}

- [Test that an API returns 401 without a token](https://zriz.io/learn/test-api-401-without-token.md)
- [Test that a failed request writes no row](https://zriz.io/learn/test-failed-request-writes-no-row.md)
- [Pipelines](https://zriz.io/docs/pipelines.md) lists each operator of a check.
