# `route.calls_past_deadline`

The outside calls a route makes could, at their slowest, take longer than the route is allowed to run.

Area 11, [External services](/docs/external-services.md); not declinable; the next step is usually the agent's.

## Why Jadpo refuses it

Every route has a deadline, 10 seconds unless `deadline:` sets another.
At the deadline the route stops, commits nothing and answers 504. Each
outside call can wait its `timeout:` on each of its attempts: a
connection's call 3 seconds three times by default, unless the
connection's `timeout:` and `retry: { attempts: }` say otherwise. An
`ai` call counts its own `timeout:` and `attempts:` the same way.

Jadpo adds these up along the longest way through the route's action,
the actions it calls included. When the sum is longer than the deadline,
a slow service would leave a call still waiting, or still to be tried
again, when the route stops. Here the courier's lookup can wait 5 seconds
three times, 15 seconds, past the route's 10.

## What it looks like

app.jadpo:

```jadpo
application {
    connections: {
        couriers: {
            package: AcmeCouriers.v1
            domains: [shipping]
            credential: config.couriers_api_key
            environment: config.couriers_environment
            timeout: 5s
        }
    }
}
```












The action makes one call to the courier, and the route runs the action
with its default deadline of 10 seconds.

domains/shipping/actions/parcel_status.jadpo:

```jadpo
use app { couriers }
use shipping/types { ParcelAnswer, ParcelQuestion }
use shared/providers/acme_couriers

/// Where a parcel is, in the courier's words.
action parcel_status(enquiry: ParcelQuestion) -> ParcelAnswer {
    var parcel_found: AcmeCouriers.Parcel = couriers.parcels.get(
        AcmeCouriers.ParcelLookup {
            id: enquiry.parcel
        }
    )
    return ParcelAnswer {
        status: parcel_found.status
    }
}
```

domains/shipping/routes/parcels.jadpo:

```jadpo
use shipping/types { ParcelAnswer, ParcelQuestion }
use shipping/actions { parcel_status }

/// Where customers ask after their parcels.
routes Parcels {
    prefix: /parcels

    /// Where a parcel is.
    POST /status {
        authentication: RouteAuthentication.none
        input: ParcelQuestion
        output: ParcelAnswer
        status: SuccessStatus.ok
        run: parcel_status(input)
    }
}
```

```text
error: `POST /parcels/status` runs `parcel_status`, whose outside calls can take 15s, longer than its 10s deadline
 --> domains/shipping/routes/parcels.jadpo:9:5
  |
9 |     POST /status {
  |     ^^^^^^^^^^^^ deadline 10s
  reason: Each outside call can wait its `timeout:` on each of its attempts, and a route's deadline covers every call on the longest way through `parcel_status`, those of the actions it calls included; at the deadline the route stops, so a call still waiting, or still to be tried again, never finishes.
  next: Give the route `deadline: 15s`, lower the `timeout:` or the attempts of the calls (a connection's `timeout:` and `retry: { attempts: }`, an `ai` call's `timeout:` and `attempts:`), or answer `202` and make the calls in a subscriber (agent)
  rule: route.calls_past_deadline
  help: https://jadpo.dev/docs/errors/route.calls_past_deadline

check failed: 1 error, 13 files
```

`(agent)` at the end of the `next:` line means your coding agent can make
the fix itself.

## How to fix it

**If the route can wait that long**, give it a longer deadline, up to 60
seconds. In `domains/shipping/routes/parcels.jadpo`:

```jadpo
        deadline: 15s
```

















The route may now run for 15 seconds, so the call's three attempts fit.
A caller may wait that long for an answer.

**If each attempt can be shorter**, lower the connection's `timeout:` in
`app.jadpo`:

```jadpo
            timeout: 3s
```

















Three attempts of 3 seconds fit within 10. A call slower than 3 seconds
now times out and is tried again sooner.

**If fewer attempts will do**, lower the connection's attempts in
`app.jadpo`:

```jadpo
            retry: {
                attempts: 2
            }
```

















Two attempts of 5 seconds fit within 10. A call that fails twice is not
tried a third time.

Work that needs longer than 60 seconds can't run in a route. The route
answers `202` and the calls run in a subscriber, code that runs when an
event is delivered.

## Related

- [Time limits](/docs/time-limits.md)
- [Time limits and retries](/docs/calling.md#time-limits-and-retries)
- [Retrying a call, and timing out](/docs/calling.md#retrying-a-call-and-timing-out)
- [Subscribers](/docs/subscribers.md)
