pool_role_unknown
A Service's role names a Pool that has no role by that name, so no member could ever be offered its Task.
| Fix | Fails in | Exit |
|---|---|---|
| Name the role as the Pool does, or add it to the Pool's roles. | services/translation.ts:10 · roles.sworn | 1 |
Owned by Pool(): your marketplace: the page that explains what this gate holds.
✗ A step performs a reserved act, and no role that does it holds the credential its row reserves it to. Give the step to a role that holds the credential, or set the role's credential to one that meets it. sign performs sign, reserved to sworn translator (rules 2026-10), and the sworn role holds no credential.
at services/translation.ts:10 · roles.sworn.credential
✗ A Service's role names a Pool that has no role by that name, so no member could ever be offered its Task. Name the role as the Pool does, or add it to the Pool's roles. translation's role sworn names the translators Pool, which fills translator.
at services/translation.ts:10 · roles.sworn
✗ 2 to fixThe same file failed reserved_act_unstaffed in the same run. Each has its own page.
import { Service } from 'services.dev'
import { translators } from '../pools/translators.ts'
import rules from '../rules.ts'
export default Service({
name: 'Translation',
input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
output: { document: 'file' },
rules,
roles: { sworn: { pool: translators } },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
sign: { by: 'sworn', stamp: true },
},
price: 89,
})diff --git a/services/translation.ts b/services/translation.ts
index 2f71f3d..e68b75e 100644
--- a/services/translation.ts
+++ b/services/translation.ts
@@ -7,11 +7,11 @@ export default Service({
input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
output: { document: 'file' },
rules,
- roles: { sworn: { pool: translators } },
+ roles: { translator: { pool: translators } },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
- sign: { by: 'sworn', stamp: true },
+ sign: { by: 'translator', stamp: true },
},
price: 89,
})✓ ready to sell · 1 Service · it keeps at least 80% of every jobimport { Pool } from 'services.dev'
export const translators = Pool({
name: 'translators',
roles: { translator: { credential: 'sworn translator' } },
join: { name: 'text', languages: 'language[]' },
verify: 'https://verify.example.test/translators',
fill: ['raise 10% 2h', 'widen 4h'],
})import { Rules } from 'services.dev'
export default Rules({
version: '2026-10',
services: {
translation: {
sign: { reserved: 'sworn translator', where: '*', position: 'A sworn translator signs a translation filed with a registry.' },
},
},
})How the legal example passes this gate, in lines read from its files.
roles: {
attorney: { credential: 'bar admission' },
practitioner: { credential: ['patent attorney', 'patent agent'], where: '*' },
// …
student: { credential: 'law school enrollment' },roles: { attorney: { pool: attorneys, pay: 50 } },Read them in context: The attorneys' Pool, Contract review.
{
"code": "pool_role_unknown",
"reason": "A Service's role names a Pool that has no role by that name, so no member could ever be offered its Task.",
"next": "Name the role as the Pool does, or add it to the Pool's roles. translation's role sworn names the translators Pool, which fills translator.",
"doc_url": "https://services.dev/docs/reference/check/pool_role_unknown",
"file": "services/translation.ts",
"line": 10,
"path": "roles.sworn"
}The whole document check --json prints
{
"ai": {
"cents_per_call": 42,
"simulated": true
},
"mcp": {
"tools": 13,
"tokens": 4488,
"sandbox": 9,
"budget": 8000
},
"files": [
{
"path": "rules.ts",
"lines": 6,
"kind": "rules",
"says": "rules 2026-10 · 1 Service · 1 row"
},
{
"path": "pools/translators.ts",