# `deployable.target_unsupported`

Deployable reaches a connection its target can't run.

Area 14, [Tooling](../topics/tooling.md); not declinable; the next step is usually the agent's.

A deployable that declares a target is held to the connections it
reaches, from the routes of the APIs it serves and the background work it
runs: the disk and a service Jadpo runs (`runs:`) without `host:` aren't
on Workers, SMTP on port 25 is blocked there, and only a Worker receives
a Cloudflare queue or counts in Cloudflare's rate-limiting binding (area
11; area 16, "Rate limits"). One built for Workers that
runs the schedules is held to them too: its tick is the minute's cron, so
a schedule more often than once a minute is refused at its `every:`
(area 12), and so is its `client_address:`:
Cloudflare's `CF-Connecting-IP` is the only source a Worker reads (area
10, "Client addresses"). Each refusal names what to use
instead. A bakery keeps its suppliers' price sheets on its disk:







```jadpo
use app { sheets }
use bakery/entities { PriceSheet }
use bakery/types { NewSheet, SheetKept }
use bakery/failures { SheetNotKept }

/// Keeps a price sheet as it was sent.
action keep_prices(input: NewSheet) fails SheetNotKept -> SheetKept {
    var sheet: File = attempt sheets.put(encoding.to_utf8(input.text), FileType.csv) {
        storage_full: SheetNotKept
    }
    var filed: PriceSheet = PriceSheet.create {
        set: {
            sheet: sheet
        }
    }
    return SheetKept {
        id: filed.id
    }
}
```



and its edge, which serves the API that keeps them, is built for Workers:

```jadpo
application {
    connections: {
        limits: {
            driver: Driver.cloudflare_rate_limits
            namespace: 1001
        }
        sheets: {
            driver: Driver.disk
            path: "/var/lib/bakery/sheets"
        }
    }
    deployables: {
        edge: {
            serves: [main]
            target: Target.wasm
        }
    }
    rate_limits: {
        store: limits
    }
}
```

```text
error: `edge` can't use `sheets` on Workers, which has no disk
 --> app.jadpo:15:21
   |
 7 |         sheets: {
   |         ------ `Driver.disk`
15 |             target: Target.wasm
   |                     ^^^^^^^^^^^ built for Workers
  reason: `sheets` keeps files on the server's own disk (`Driver.disk`), and a Worker has none; `edge` uses it through `keep_prices`.
  next: Keep `sheets`'s files through a package over S3's API, such as Cloudflare R2, or use them from a `Target.native` deployable (agent)
  rule: deployable.target_unsupported
  help: https://jadpo.dev/docs/errors/deployable.target_unsupported

check failed: 1 error, 8 files
```

Another bakery checks its ovens' temperatures twice a minute:



```jadpo
use bakery/actions { check_ovens }

/// Checks the ovens twice a minute.
schedule oven_check {
    every: 30s
    run: check_ovens()
}
```

and runs its schedules on Workers:

```jadpo
application {
    connections: {
        main: {
            driver: Driver.postgres
        }
    }
    deployables: {
        edge: {
            runs: [Trigger.schedules, Trigger.subscribers]
            target: Target.wasm
        }
    }
}
```

```text
error: `edge` can't run `oven_check` every 30 seconds on Workers, whose cron runs once a minute
 --> domains/bakery/schedules/oven_check.jadpo:5:12
  |
5 |     every: 30s
  |            ^^^ more often than once a minute
  reason: A Worker ticks when Cloudflare's cron trigger runs it, once a minute at most, so a schedule due every 30 seconds would run late; `edge` runs `oven_check` because its `runs:` lists `Trigger.schedules`.
  next: Give `oven_check` `every: 1m` or longer, or run `Trigger.schedules` in a `Target.native` deployable (agent)
  rule: deployable.target_unsupported
  help: https://jadpo.dev/docs/errors/deployable.target_unsupported

check failed: 1 error, 3 files
```

A third bakery reads its customers' addresses from its load balancer's
`X-Forwarded-For`, and serves them from Workers:

```jadpo
application {
    client_address: {
        source: ClientAddressSource.forwarded_for
        hops: 1
    }
    connections: {
        limits: {
            driver: Driver.cloudflare_rate_limits
            namespace: 1001
        }
    }
    deployables: {
        edge: {
            serves: [main]
            target: Target.wasm
        }
    }
    rate_limits: {
        store: limits
    }
}
```

```text
error: `edge` can't read the client's address from `X-Forwarded-For` on Workers
 --> app.jadpo:3:17
   |
 3 |         source: ClientAddressSource.forwarded_for
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not read on Workers
15 |             target: Target.wasm
   |                     ----------- built for Workers
  reason: Cloudflare writes the client's address in `CF-Connecting-IP` on every request, overwriting a caller's, and a Worker has no connection address of its own, so `cloudflare` is the only source a Worker reads; `edge` would refuse to start.
  next: Use `ClientAddressSource.cloudflare` without `hops:`, or build `edge` with `Target.native` (agent)
  rule: deployable.target_unsupported
  help: https://jadpo.dev/docs/errors/deployable.target_unsupported

check failed: 1 error, 1 file
```
