Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 1 Nov 2026. What's built · Install 0.2.0
jadpo
Reference: Built-in services

Built-in services · rule

threshold.declaration_invalid

On this page

A threshold in thresholds { } doesn't watch one thing, gives a limit that doesn't apply to it, or gives a value a limit can't take.

Area 16, Built-in services; not declinable; the next step is usually the agent's.

Why Jadpo refuses it

A threshold watches one route, action, query, schedule or subscriber, and each of its limits is an upper bound on something that one thing does. A limit that can't apply, such as the age of the oldest waiting delivery on an action, which has no deliveries, would generate a rule that never fires; a value of the wrong kind has no bound to judge. Thresholds live in a domain's monitoring.jadpo so a reviewer reads every one that watches the domain in one place.

What it looks like

counting gives oldest_waiting:, which only a subscriber's deliveries have:

example
/// How many visitors have come.type VisitorCount = Int {    min: 0}/// How many visitors have come so far.action count_visitors() -> VisitorCount {    return 1}thresholds {    /// Counting the visitors stays quick.    counting: {        watches: count_visitors        oldest_waiting: 5m    }}
jadpo checkcheck failed: 1 error, 1 file

error oldest_waiting: can't watch an action

--> main.jadpo:15:25

   |15 |         oldest_waiting: 5m   |                         ^^ not for an action
reason
oldest_waiting: is the age a subscriber's oldest waiting delivery may reach, a duration above zero. It watches a subscriber.
next
Remove oldest_waiting: from counting (agent)
rule
threshold.declaration_invalid
help
https://jadpo.dev/docs/errors/threshold.declaration_invalid

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

A percentile shorter than a lower one beside it is refused too, since no request could meet it:

example
/// How many visitors have come.type VisitorCount = Int {    min: 0}/// How many visitors have come so far.action count_visitors() -> VisitorCount {    return 1}thresholds {    /// Counting the visitors stays quick.    counting: {        watches: count_visitors        p50: 80ms        p99: 50ms    }}
jadpo checkcheck failed: 1 error, 1 file

error p99: on counting is shorter than its p50:

--> main.jadpo:16:14

   |16 |         p99: 50ms   |              ^^^^ shorter than a lower percentile
reason
A percentile counts the requests done within its time, so a higher one takes at least as long as a lower one: no p99: can be met while a shorter one beside it isn't.
next
Make p99: at least p50:'s, or remove one (agent)
rule
threshold.declaration_invalid
help
https://jadpo.dev/docs/errors/threshold.declaration_invalid

How to fix it

If the limit doesn't apply, give one that does. An action's runs have a duration, a share that fails on the server and percentiles:

example
    counting: {        watches: count_visitors        p99: 50ms    }

counting now judges the action's runs by how long 99% of them take, which the rules made from it alert on.

If the percentiles are the wrong way round, make each higher one at least as long as the one below it:

example
        p50: 30ms        p99: 50ms

Half the runs must now finish within 30 ms and 99% within 50 ms, which both can.

Markdown for agents: /docs/errors/threshold.declaration_invalid.md.Built from Jadpo main at e00e61f.