# Error reference

Every Homespun API error carries a stable `code`, an HTTP `status`, a short `hint`, a `retryable` flag, and a `docs_url`. The `docs_url` is the anchored entry on this page (`https://docs.homespun.dev/reference/errors#<code>`), so an agent that receives an error can follow it straight to the matching section.

This page is generated at build time from the relay error registry (`packages/relay/src/http/errors.ts`), so it can never drift from the codes the API actually returns. Sections are ordered by code.

## account\_quota\_exceeded

[Section titled “account\_quota\_exceeded”](#account_quota_exceeded)

**HTTP 409** · client error · not retryable

account apps quota reached (max 100)

**Hint.** this cap applies across your whole account; delete unused apps/rows/attachments to free quota, or ask the operator to raise the matching MAX\_\*\_PER\_ACCOUNT limit (or upgrade the plan)

**Remediation.** This cap spans your whole account, not one app. Delete unused apps, rows, or attachments to free the tripped dimension, ask the operator to raise the matching `MAX_*_PER_ACCOUNT` limit, or upgrade the plan.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## agent\_not\_claimed

[Section titled “agent\_not\_claimed”](#agent_not_claimed)

**HTTP 403** · client error · not retryable

this agent must be claimed by a human before it can deploy an app

**Hint.** claim this agent first: open /get-started on the relay, generate a claim code, then run homespun agent claim \<code> and retry the deploy

**Remediation.** Deploying an app needs a human owner. Ask a human to open `/get-started` and generate a claim code, then run `homespun agent claim <code>` and redeploy. Device-flow-registered agents are already claimed.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## app\_not\_found

[Section titled “app\_not\_found”](#app_not_found)

**HTTP 404** · client error · not retryable

**Hint.** the app id/slug is wrong, or the app does not belong to the calling agent’s owner; run ‘homespun apps list’ to find the right id

**Remediation.** The app id or slug is wrong, or the app belongs to another owner. Run `homespun apps list` to find an app you own and use its id.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## app\_quota\_exceeded

[Section titled “app\_quota\_exceeded”](#app_quota_exceeded)

**HTTP 409** · client error · not retryable

app rows quota reached (max 1000)

**Hint.** delete existing rows to free quota, or ask the operator to raise MAX\_ROWS\_PER\_APP / MAX\_STORAGE\_BYTES\_PER\_APP

**Remediation.** The app hit its row or storage quota. Delete existing rows to free space, or ask the operator to raise `MAX_ROWS_PER_APP` / `MAX_STORAGE_BYTES_PER_APP`.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## append\_only

[Section titled “append\_only”](#append_only)

**HTTP 403** · client error · not retryable

collection ‘\<collection>’ is append-only: rows cannot be updated or deleted

**Hint.** append-only collections accept create only, model an edit as a new row, or declare the collection with appendOnly:false in the manifest

**Remediation.** The collection is append-only: create rows only, never update or delete. Model an edit as a new row, or declare the collection with `appendOnly:false` in the manifest if edits are legitimate.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## attachment\_not\_found

[Section titled “attachment\_not\_found”](#attachment_not_found)

**HTTP 404** · client error · not retryable

**Hint.** the attachment id is wrong, the attachment was deleted, or it does not belong to the calling agent; run ‘homespun attachment list’ to find the right id

**Remediation.** The attachment id is wrong, the attachment was deleted, or it belongs to another agent. Run `homespun attachment list` to find an id you own and reference that.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## attachment\_ref\_not\_accessible

[Section titled “attachment\_ref\_not\_accessible”](#attachment_ref_not_accessible)

**HTTP 422** · client error · not retryable

attachment ref(s) not accessible: \<attachment\_id>

**Hint.** the payload references one or more attachment ids the calling agent does not own (or that have been deleted); upload the attachment with POST /v1/attachments and use the returned attachment\_id, or check ‘homespun attachment list’ for ids you actually own

**Remediation.** The payload references attachment ids the calling agent does not own or that were deleted. Upload the attachment (`POST /v1/attachments`) and use the returned `attachment_id`, or check `homespun attachment list` for ids you own. On the read side, an attachment is reachable only when it is referenced from this app events or initial `input_data` and is not soft-deleted.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## attachment\_size\_exceeded

[Section titled “attachment\_size\_exceeded”](#attachment_size_exceeded)

**HTTP 413** · client error · not retryable

attachment exceeds the per-attachment cap of 1048576 bytes

**Hint.** downscale or compress the attachment to fit; for images, the client SDK does this automatically (max dimension + JPEG quality)

**Remediation.** Shrink the attachment below the per-attachment cap. For images the client SDK downscales automatically (max dimension plus JPEG quality); otherwise compress or resize before uploading.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## attachment\_token\_invalid

[Section titled “attachment\_token\_invalid”](#attachment_token_invalid)

**HTTP 401** · client error · not retryable

**Hint.** the attachment token is unknown, expired, revoked, or has been spent (once-tokens); request a fresh token from the agent that owns the attachment

**Remediation.** Request a new attachment token from the agent that owns the attachment. Attachment tokens expire, can be revoked, and once-tokens are single-use, so a fresh token is the fix.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## attachment\_token\_not\_found

[Section titled “attachment\_token\_not\_found”](#attachment_token_not_found)

**HTTP 404** · client error · not retryable

**Hint.** the token id is wrong, or the token does not belong to this attachment; run ‘homespun attachment show \<id>’ to list active tokens

**Remediation.** The token id is wrong or does not belong to this attachment. Run `homespun attachment show <id>` to list the attachment active tokens and use one of those.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## author\_not\_allowed

[Section titled “author\_not\_allowed”](#author_not_allowed)

**HTTP 403** · client error · not retryable

**Hint.** only the row author may perform this action

**Remediation.** Only the row author may perform this action. Act as the identity that created the row, or use an owner/agent path if one exists for the operation.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## capability\_invalid

[Section titled “capability\_invalid”](#capability_invalid)

**HTTP 400** · client error · not retryable

capabilities entry ‘\<value>’ is invalid

**Hint.** capabilities must be an array of strings drawn from {camera, microphone, geolocation}, with no duplicates

**Remediation.** Set `capabilities` to an array of names drawn from the allowed list, with no duplicates. Remove the unknown value; the message lists the exact allowed names.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## cli\_upgrade\_required

[Section titled “cli\_upgrade\_required”](#cli_upgrade_required)

**HTTP 426** · client error · not retryable

this relay requires @homespunapps/cli >= \<min\_version> (you sent \<your\_version>)

**Hint.** upgrade the @homespunapps/cli package to >= \<min\_version> and retry; non-CLI library callers can omit the x-homespun-cli-version header to opt out of this check

**Remediation.** Upgrade `@homespunapps/cli` to at least the required version and rerun. Library callers that are not the CLI can omit the `x-homespun-cli-version` header to opt out of the minimum-version check.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## collection\_count\_forbidden

[Section titled “collection\_count\_forbidden”](#collection_count_forbidden)

**HTTP 403** · client error · not retryable

reading the row count of collection ‘\<collection>’ is not permitted for this principal

**Hint.** count requires one of: anyone

**Remediation.** The collection does not expose its count to your principal. Declare a `countRead` role list on the collection to opt into a count-only aggregate, then read the count as an allowed role.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_delete\_forbidden

[Section titled “collection\_delete\_forbidden”](#collection_delete_forbidden)

**HTTP 403** · client error · not retryable

deleting from collection ‘\<collection>’ is not permitted for this principal

**Hint.** delete requires one of: owner

**Remediation.** Your principal is not in the collection `delete` role list. Act as an allowed role, or widen the collection `delete` list in the manifest and redeploy.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_name\_invalid

[Section titled “collection\_name\_invalid”](#collection_name_invalid)

**HTTP 400** · client error · not retryable

collection name ‘\<name>’ is invalid

**Hint.** collection names must start with a lowercase letter and contain only lowercase letters, digits, ’\_’, or ’-’ (max 64 chars)

**Remediation.** Rename the collection to start with a lowercase letter and use only lowercase letters, digits, `_`, or `-`, up to 64 characters.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_not\_found

[Section titled “collection\_not\_found”](#collection_not_found)

**HTTP 404** · client error · not retryable

collection ‘\<name>’ is not declared on this app

**Hint.** the collection name must match one declared in the app’s manifest (x-homespun-manifest.collections); redeploy with the collection declared, or check the name

**Remediation.** The collection is not declared on this app. Redeploy with the collection in `x-homespun-manifest.collections`, or correct the name to one that is declared.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_read\_forbidden

[Section titled “collection\_read\_forbidden”](#collection_read_forbidden)

**HTTP 403** · client error · not retryable

reading collection ‘\<collection>’ is not permitted for this principal

**Hint.** read requires one of: owner, agent

**Remediation.** Your principal is not in the collection `read` role list. Sign in as an allowed role (on a public app your page must call `homespun.session.login()`), or adjust the collection `read` list in the manifest.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_schema\_invalid

[Section titled “collection\_schema\_invalid”](#collection_schema_invalid)

**HTTP 400** · client error · not retryable

the collection schema is invalid

**Hint.** schema must be { “$ref”: ”#/$defs/\<Name>” }, resolve to an object under $defs, and compile as JSON Schema 2020-12

**Remediation.** A collection schema must be `{ "$ref": "#/$defs/<Name>" }`, resolve to an object under `$defs`, and compile as JSON Schema 2020-12. Inline any sibling `$defs` ref (cross-`$defs` refs are not resolved) and keep each string `maxLength` within the per-row byte cap.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## collection\_write\_forbidden

[Section titled “collection\_write\_forbidden”](#collection_write_forbidden)

**HTTP 403** · client error · not retryable

writing to collection ‘\<collection>’ is not permitted for this principal

**Hint.** write requires one of: agent, owner

**Remediation.** Your principal is not in the collection `write` role list. Act as a role the collection allows to write, or widen the collection `write` list in the manifest and redeploy.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## community\_publish\_disabled

[Section titled “community\_publish\_disabled”](#community_publish_disabled)

**HTTP 403** · client error · not retryable

**Hint.** publishing to the community gallery is disabled on this relay

**Remediation.** Publishing to the community gallery is turned off on this relay. Ask the operator to enable community publishing, or keep the app private or link-visible instead.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## conflict

[Section titled “conflict”](#conflict)

**HTTP 409** · client error · not retryable

**Hint.** the request conflicts with the current state of the resource

**Remediation.** The request conflicts with the resource current state. Re-read the resource, rebase your change on the latest version, and retry. For an optimistic-lock (`if_match`) mismatch, rebase against `details.current` and resend with its version.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## connection\_invalid

[Section titled “connection\_invalid”](#connection_invalid)

**HTTP 400** · client error · not retryable

a connection field is invalid

**Hint.** check the connection field named in the message: name is \[a-z0-9]\[a-z0-9\_-]{0,63}; allowedHost is a bare DNS host or a single leftmost ’\*.’ wildcard; a static connection needs headerName + headerValue; oauth2 connections are created via the consent flow (a later build)

**Remediation.** Fix the connection field named in the message. `name` is `[a-z0-9][a-z0-9_-]{0,63}`; `allowedHost` is a bare DNS host or a single leftmost `*.` wildcard; a static connection needs `headerName` plus `headerValue`; oauth2 connections are created through the consent flow.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## connection\_limit\_reached

[Section titled “connection\_limit\_reached”](#connection_limit_reached)

**HTTP 409** · client error · not retryable

this app already has the maximum of 20 connections

**Hint.** delete an unused connection (DELETE /v1/apps/:id/connections/:name) before creating another, or ask the operator to raise MAX\_CONNECTIONS\_PER\_APP

**Remediation.** The app is at `MAX_CONNECTIONS_PER_APP`. Delete an unused connection (`DELETE /v1/apps/:id/connections/:name`) before creating another, or ask the operator to raise the cap.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## connection\_not\_found

[Section titled “connection\_not\_found”](#connection_not_found)

**HTTP 404** · client error · not retryable

no connection named ‘\<name>’ on this app

**Hint.** the connection name is wrong or it was deleted; list connections with GET /v1/apps/:id/connections

**Remediation.** No connection by that name exists on this app. List connections with `GET /v1/apps/:id/connections` and reference one that exists, or create it first.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## consent\_owner\_only

[Section titled “consent\_owner\_only”](#consent_owner_only)

**HTTP 403** · client error · not retryable

**Hint.** only the app owner may grant this consent

**Remediation.** Only the app owner may grant this consent. Have the owner complete the consent step in a browser; an agent key cannot grant it.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## csrf\_origin\_mismatch

[Section titled “csrf\_origin\_mismatch”](#csrf_origin_mismatch)

**HTTP 403** · client error · not retryable

**Hint.** the request Origin or Referer did not match the expected site origin

**Remediation.** The request `Origin`/`Referer` did not match the expected site origin. Issue the request from the app own page so the browser sends a matching origin, and do not strip these headers.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## custom\_domains\_not\_enabled

[Section titled “custom\_domains\_not\_enabled”](#custom_domains_not_enabled)

**HTTP 501** · server error · not retryable

custom domains are not enabled on this deployment

**Hint.** the relay operator has not configured Cloudflare for SaaS (CLOUDFLARE\_API\_TOKEN, CLOUDFLARE\_ZONE\_ID, CUSTOM\_DOMAINS\_CNAME\_TARGET); ask them to enable it, or use the app’s built-in subdomain

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## domain\_exists

[Section titled “domain\_exists”](#domain_exists)

**HTTP 409** · client error · not retryable

this app already has a custom domain (‘\<domain>’)

**Hint.** an app can hold one custom domain; DELETE /v1/apps/:id/domain first to replace it

**Remediation.** An app holds one custom domain at a time. Send `DELETE /v1/apps/:id/domain` to remove the current one before adding another.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## domain\_invalid

[Section titled “domain\_invalid”](#domain_invalid)

**HTTP 400** · client error · not retryable

the domain is invalid

**Hint.** send a bare, valid DNS name you control (e.g. app.example.com) - platform domains and their subdomains, IP literals, wildcards, and local/reserved names are rejected

**Remediation.** Send a bare, valid DNS name you control (for example `app.example.com`). Platform domains and their subdomains, IP literals, wildcards, and local or reserved names are rejected.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## domain\_not\_found

[Section titled “domain\_not\_found”](#domain_not_found)

**HTTP 404** · client error · not retryable

**Hint.** this app has no custom domain; POST /v1/apps/:id/domain to add one

**Remediation.** This app has no custom domain configured. Send `POST /v1/apps/:id/domain` to add one.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## domain\_taken

[Section titled “domain\_taken”](#domain_taken)

**HTTP 409** · client error · not retryable

domain ‘\<domain>’ is already in use

**Hint.** that domain is already bound to an app on this relay; remove it from the other app first, or use a different domain

**Remediation.** That domain is already bound to another app on this relay. Remove it from the other app first, or use a different domain.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## email\_not\_verified

[Section titled “email\_not\_verified”](#email_not_verified)

**HTTP 403** · client error · not retryable

**Hint.** verify your account email before performing this action

**Remediation.** Verify your account email before performing this action. Complete the verification link the relay sent, then retry.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## embed\_invalid

[Section titled “embed\_invalid”](#embed_invalid)

**HTTP 400** · client error · not retryable

embeds entry ‘\<origin>’ is invalid: not an https origin

**Hint.** embeds entries must be https origins (an optional single leading ’\*.’ wildcard is allowed when >= 2 labels remain), with no path/query/fragment/userinfo, no IP literals, no duplicates, and must not name the app’s own origin

**Remediation.** Give each `embeds` entry as an https origin with the same grammar as `externalHosts` (host only, optional single leading `*.` wildcard, no path, query, fragment, userinfo, or IP), no duplicates, and not the app own origin.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## external\_host\_invalid

[Section titled “external\_host\_invalid”](#external_host_invalid)

**HTTP 400** · client error · not retryable

externalHosts entry ‘\<host>’ is invalid: not an https origin

**Hint.** externalHosts entries must be https origins (an optional single leading ’\*.’ wildcard is allowed when >= 2 labels remain), with no path/query/fragment/userinfo, no IP literals, no duplicates, and must not name the app’s own origin

**Remediation.** Give each `externalHosts` entry as an https origin (host only, an optional single leading `*.` wildcard with at least two remaining labels), with no path, query, fragment, userinfo, or IP literal, no duplicates, and not the app own origin.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## forbidden

[Section titled “forbidden”](#forbidden)

**HTTP 403** · client error · not retryable

**Hint.** the authenticated identity is not permitted to perform this action

**Remediation.** The token is valid but this identity may not perform the action. Confirm you are acting as the app owner or owning agent, and that the target collection or resource permits your role.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## gone

[Section titled “gone”](#gone)

**HTTP 410** · client error · not retryable

app is closed

**Hint.** the app is closed or expired and cannot accept new events; create a new app to continue

**Remediation.** The app is closed or expired and cannot accept new events. Deploy or create a new app and send new traffic there.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## grant\_invalid

[Section titled “grant\_invalid”](#grant_invalid)

**HTTP 401** · client error · not retryable

**Hint.** the grant is missing, already used, expired, or was minted for a different app; restart sign-in via GET /authorize

**Remediation.** The session grant is missing, already used, expired, or minted for a different app. Restart sign-in from `GET /authorize` (`homespun.session.login()` does this for a page) to obtain a fresh grant.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## ingest\_invalid

[Section titled “ingest\_invalid”](#ingest_invalid)

**HTTP 400** · client error · not retryable

an ingest rule is malformed

**Hint.** check the named ingest rule field against the x-homespun-manifest.ingest grammar (name is \[a-z0-9]\[a-z0-9\_-]{0,63} and unique in the app; collection must be declared; mode ∈ {append,upsert} and upsert requires upsertOn naming a collection unique field; map values and dedupeKey are dot-paths into the JSON body; handshake is ‘echo’; wake is a boolean)

**Remediation.** Fix the ingest rule field named in the message. `name` is `[a-z0-9][a-z0-9_-]{0,63}` and unique within the app, `collection` must be declared, and `mode` is append or upsert (upsert requires `upsertOn` naming one of the collection’s unique fields). `map` values and `dedupeKey` are dot-paths into the JSON body; `handshake` is `echo`; `wake` is a boolean.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## ingest\_not\_found

[Section titled “ingest\_not\_found”](#ingest_not_found)

**HTTP 404** · client error · not retryable

**Hint.** the catch-hook URL is wrong (unknown hook, bad secret, or a disabled hook); copy the exact POST /v1/ingest/\<hookId>/\<secret> URL from the app’s inbound-hooks panel or rotate the secret

**Remediation.** The catch-hook URL is wrong: no such hook, a bad secret, or the hook was disabled (its rule was removed from the manifest). Both an unknown hook and a bad secret return this same 404 on purpose, so the endpoint is not an existence oracle. Copy the exact `POST /v1/ingest/<hookId>/<secret>` URL from the app’s inbound-hooks panel, or rotate the secret to get a fresh URL.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## ingest\_payload\_too\_large

[Section titled “ingest\_payload\_too\_large”](#ingest_payload_too_large)

**HTTP 413** · client error · not retryable

**Hint.** the inbound catch-hook body exceeds INGEST\_MAX\_BODY\_BYTES (64 KiB by default); send a smaller payload

**Remediation.** Send a smaller body. The inbound catch-hook accepts at most `INGEST_MAX_BODY_BYTES` (64 KiB by default) per request; trim or split the payload to fit.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## ingest\_signature\_invalid

[Section titled “ingest\_signature\_invalid”](#ingest_signature_invalid)

**HTTP 401** · client error · not retryable

**Hint.** the inbound catch-hook requires a valid body signature and this request’s signature did not verify; provision the hook’s signing secret with \`homespun ingest signing-secret set\` and paste it into the provider’s webhook Secret field (for GitHub set the webhook content type to application/json)

**Remediation.** The catch-hook opted into signature verification (`verify` in the manifest) and the request’s signature did not verify. A missing signature header, a malformed header, a wrong signature, and a hook whose signing secret is not yet provisioned all return this same 401 on purpose, so the endpoint gives an attacker nothing. Provision the hook’s signing secret with `homespun ingest signing-secret set` and paste that value into the provider’s webhook Secret field (for GitHub, also set the webhook Content type to `application/json`). This request was NOT journaled, so it will not appear in the delivery log.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## ingest\_unsupported\_media\_type

[Section titled “ingest\_unsupported\_media\_type”](#ingest_unsupported_media_type)

**HTTP 415** · client error · not retryable

**Hint.** the inbound catch-hook accepts application/json only in v1; send Content-Type: application/json

**Remediation.** Send `Content-Type: application/json`. The inbound catch-hook accepts a JSON body only in v1; form-encoded, multipart, and other content types are rejected.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## ingest\_write\_unavailable

[Section titled “ingest\_write\_unavailable”](#ingest_write_unavailable)

**HTTP 503** · server error · retryable

the inbound delivery could not be stored: the app is at its row or storage quota

**Hint.** the app is temporarily full; the delivery was recorded as failed and no row was written. Retry later (the owner can free space by deleting rows or raising MAX\_ROWS\_PER\_APP / MAX\_STORAGE\_BYTES\_PER\_APP), or the owner can replay it from the inbound-hooks panel once space frees.

**Remediation.** The app is at its row or storage quota, so the inbound delivery could not be stored. This is transient: the delivery was journaled as `failed` and no row was written, so back off and redeliver later. The app owner can free space (delete rows, or raise `MAX_ROWS_PER_APP` / `MAX_STORAGE_BYTES_PER_APP`) and replay the delivery from the inbound-hooks panel.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## input\_schema\_violation

[Section titled “input\_schema\_violation”](#input_schema_violation)

**HTTP 422** · client error · not retryable

**Hint.** the event does not satisfy the app’s event schema; check the event type and payload against the declared schema

**Remediation.** The initial `input_data` failed the target collection schema. Fix the fields named in `details` so the seed data validates, then redeploy or recreate.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## invalid\_request

[Section titled “invalid\_request”](#invalid_request)

**HTTP 400** · client error · not retryable

**Hint.** the request body or parameters are malformed; check the field named in the message against the API spec

**Remediation.** Fix the malformed field named in the message and resend. Check the request body and query parameters against the endpoint shape (`homespun <command> --help` documents the CLI surface).

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## manifest\_incompatible\_redeploy

[Section titled “manifest\_incompatible\_redeploy”](#manifest_incompatible_redeploy)

**HTTP 422** · client error · not retryable

**Hint.** the new manifest narrows the app’s current manifest in one or more places; either publish a manifest that’s a superset, or retry with force=true to proceed (a narrowed/removed collection is detached, not deleted)

**Remediation.** The new manifest narrows the app current one. Publish a manifest that is a superset of the live one, or retry with `force=true` to proceed, which detaches (never deletes) a narrowed or removed collection.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## manifest\_invalid

[Section titled “manifest\_invalid”](#manifest_invalid)

**HTTP 400** · client error · not retryable

the manifest top-level shape is invalid

**Hint.** the manifest’s top-level shape is wrong; check the field named in the message against the x-homespun-manifest grammar

**Remediation.** Fix the manifest field named in the message. The top-level shape is wrong; validate your document against the `x-homespun-manifest` grammar (see the manifest reference) and redeploy.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## manifest\_too\_large

[Section titled “manifest\_too\_large”](#manifest_too_large)

**HTTP 413** · client error · not retryable

the manifest exceeds the configured size limit

**Hint.** shrink the manifest (or the offending $defs row schema) below the configured MAX\_MANIFEST\_BYTES / MAX\_SCHEMA\_BYTES limit

**Remediation.** Shrink the manifest below `MAX_MANIFEST_BYTES`, or the offending `$defs` row schema below `MAX_SCHEMA_BYTES`. Remove unused `$defs`, flatten deep nesting, and trim long descriptions.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## method\_not\_allowed

[Section titled “method\_not\_allowed”](#method_not_allowed)

**HTTP 405** · client error · not retryable

**Hint.** the request HTTP method is not supported on this route; see the Allow response header for the verbs that are

**Remediation.** Use one of the HTTP verbs the route supports. The response `Allow` header lists the verbs that are valid on this path.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## mime\_disallowed

[Section titled “mime\_disallowed”](#mime_disallowed)

**HTTP 415** · client error · not retryable

MIME ‘\<mime>’ is not in this relay’s BLOB\_MIME\_ALLOWLIST

**Hint.** upload a file matching one of the allowed MIME prefixes; ask the operator to widen BLOB\_MIME\_ALLOWLIST if a missing prefix is legitimate

**Remediation.** Upload a file whose sniffed MIME is in the relay `BLOB_MIME_ALLOWLIST`. Convert the file to an allowed format, or ask the operator to add the prefix if it is legitimate.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## mime\_mismatch

[Section titled “mime\_mismatch”](#mime_mismatch)

**HTTP 415** · client error · not retryable

declared Content-Type ‘\<declared>’ does not match the sniffed ‘\<sniffed>’

**Hint.** send a Content-Type that matches the file’s actual format; the server validates leading bytes and refuses the upload on mismatch

**Remediation.** Send a `Content-Type` that matches the file real bytes. The relay sniffs the leading bytes and refuses an upload whose declared type disagrees; re-detect the type or re-encode the file.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## not\_a\_reviewer

[Section titled “not\_a\_reviewer”](#not_a_reviewer)

**HTTP 403** · client error · not retryable

**Hint.** only a designated reviewer may perform this action

**Remediation.** Only a designated reviewer may perform this action. Ask an owner to grant the reviewer role, or act as an identity that already holds it.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## not\_found

[Section titled “not\_found”](#not_found)

**HTTP 404** · client error · not retryable

**Hint.** the resource id may be wrong, or the resource was cleaned up; verify the id and try again

**Remediation.** Verify the resource id. Ids come back from the create call and the relevant list command; a resource that was cleaned up or never existed reads the same way.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## not\_implemented

[Section titled “not\_implemented”](#not_implemented)

**HTTP 501** · server error · not retryable

\<capability> is not implemented on this relay

**Hint.** this relay does not implement the requested capability

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## notify\_invalid

[Section titled “notify\_invalid”](#notify_invalid)

**HTTP 400** · client error · not retryable

a notify rule is malformed

**Hint.** check the named notify rule field against the x-homespun-manifest.notify grammar (on ∈ {create,update}; collection must be declared; to is a non-empty array of roles {owner, members}; subject/body are plain-text templates)

**Remediation.** Fix the notify rule field named in the message. `on` is create or update, `collection` must be declared, `to` is a non-empty array of roles ({owner, members}), and `subject`/`body` are plain-text templates. See the manifest reference notify section.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## notify\_submitter\_not\_enabled

[Section titled “notify\_submitter\_not\_enabled”](#notify_submitter_not_enabled)

**HTTP 400** · client error · not retryable

notify rule on collection ‘\<collection>’ targets the ‘submitter’ role, but external (submitter) sending is not enabled on this relay

**Hint.** Phase 1 supports the ‘owner’ and ‘members’ roles only. External submitter/customer-confirmation emails are a later phase; remove ‘submitter’ from \`to\`, or ask the operator to enable NOTIFY\_EXTERNAL\_ENABLED once that phase ships.

**Remediation.** External submitter emails are disabled on this relay. Remove `submitter` from the rule `to` (use `owner` or `members`), or ask the operator to enable `NOTIFY_EXTERNAL_ENABLED` once that phase ships.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## participant\_token\_invalid

[Section titled “participant\_token\_invalid”](#participant_token_invalid)

**HTTP 401** · client error · not retryable

**Hint.** the participant token is unknown, malformed, or revoked; the agent can mint a fresh one via POST /v1/apps or by revoking + re-creating the app

**Remediation.** Mint a fresh participant token. The current one is unknown, malformed, or revoked; create a new app (`POST /v1/apps`), or revoke and recreate, then hand the browser the new token.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## payload\_too\_large

[Section titled “payload\_too\_large”](#payload_too_large)

**HTTP 413** · client error · not retryable

**Hint.** the payload exceeds the configured size cap (MAX\_ARTIFACT\_BYTES for templates, MAX\_EVENT\_DATA\_BYTES for event data, MAX\_TASTE\_BYTES for taste notes); send a smaller payload

**Remediation.** Send a smaller payload. The relevant cap is `MAX_ARTIFACT_BYTES` (templates), `MAX_EVENT_DATA_BYTES` (event data), or `MAX_TASTE_BYTES` (taste notes); split or trim the content to fit.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## permission\_role\_invalid

[Section titled “permission\_role\_invalid”](#permission_role_invalid)

**HTTP 400** · client error · not retryable

a permission role is invalid

**Hint.** write/delete must be non-empty arrays drawn from {agent, owner, member, anyone, author}: ‘author’ is never valid in write

**Remediation.** Set each of `write` and `delete` to a non-empty array drawn from {agent, owner, member, anyone, author}. `author` is never valid in `write`, since a create has no prior row to attribute.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## purge\_forbidden

[Section titled “purge\_forbidden”](#purge_forbidden)

**HTTP 403** · client error · not retryable

**Hint.** only the app owner or owning agent may purge a row

**Remediation.** Only the app owner or the owning agent may purge a row. Purge bypasses the append-only rule and the collection `delete` list on purpose, so it is restricted to owner/agent; act as one of those, or use a normal delete where the collection permits it.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## quota\_exceeded

[Section titled “quota\_exceeded”](#quota_exceeded)

**HTTP 413** · client error · not retryable

agent attachment quota of 1048576 bytes reached

**Hint.** delete unused attachments in this scope and retry, or ask the operator to widen the configured quota

**Remediation.** The per-scope attachment quota is full. Delete unused attachments in this scope (agent or app) and retry, or ask the operator to raise the configured quota.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## rate\_limited

[Section titled “rate\_limited”](#rate_limited)

**HTTP 429** · client error · retryable

**Hint.** the rate limit was exceeded; wait before retrying, back off and try the request again

**Remediation.** Back off and retry after a short pause. This limiter is per IP over a rolling window; honour any `Retry-After` hint, add jitter, and avoid tight retry loops.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## resync\_required

[Section titled “resync\_required”](#resync_required)

**HTTP 410** · client error · not retryable

the requested feed cursor is below the retention floor; resync from a full collection snapshot

**Hint.** drop the since cursor and re-list each collection (GET …/collections/:name), then resume watching from the newest feed cursor

**Remediation.** Your feed cursor is below the retention floor, so a contiguous replay is impossible. Drop the `since` cursor, re-list each collection for a full snapshot, then resume watching from the newest feed cursor.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## row\_not\_found

[Section titled “row\_not\_found”](#row_not_found)

**HTTP 404** · client error · not retryable

no row at key ‘\<key>’ in collection ‘\<collection>’

**Hint.** the row may have been deleted, or the key is wrong; list the collection to see current rows

**Remediation.** No live row exists at that key (soft-deleted rows read as absent). List the collection to see current keys, or create the row first.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## row\_schema\_violation

[Section titled “row\_schema\_violation”](#row_schema_violation)

**HTTP 422** · client error · not retryable

**Hint.** the event does not satisfy the app’s event schema; check the event type and payload against the declared schema

**Remediation.** The row `data` failed the collection JSON Schema. The failing schema paths are listed in the error `details`; correct those fields and retry. A non-conforming write never lands.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## schedule\_invalid

[Section titled “schedule\_invalid”](#schedule_invalid)

**HTTP 400** · client error · not retryable

a schedules rule is malformed

**Hint.** check the named schedules rule field against the x-homespun-manifest.schedules grammar (collection must be declared; dateField a field of it; offsetDays an integer, negative = before / 0 = on / positive = after; to is a non-empty array of {owner, members}; when is an optional level condition; subject/body are plain-text templates)

**Remediation.** Fix the schedules rule field named in the message. `collection` must be declared, `dateField` a field of it, `offsetDays` an integer (negative before, 0 on, positive after), `to` a non-empty array of {owner, members}, and `subject`/`body` plain-text templates.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## schema\_incompatible\_upgrade

[Section titled “schema\_incompatible\_upgrade”](#schema_incompatible_upgrade)

**HTTP 422** · client error · not retryable

**Hint.** the target template version narrows the app’s current schema in one or more places; either publish a wider template version that’s a superset, or retry with compat=“force” to skip the gate (events written under the old schema may no longer validate)

**Remediation.** The target template version narrows the app current schema, so past events might stop validating. Publish a wider template version that is a superset, or retry with `compat="force"` to accept the narrowing.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## schema\_violation

[Section titled “schema\_violation”](#schema_violation)

**HTTP 422** · client error · not retryable

**Hint.** the event does not satisfy the app’s event schema; check the event type and payload against the declared schema

**Remediation.** The event or row does not satisfy the collection declared JSON Schema. Read the failing paths in `details`, correct the payload to match the schema, and resend. A schemaless collection accepts any shape.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## slug\_not\_allowed\_for\_link

[Section titled “slug\_not\_allowed\_for\_link”](#slug_not_allowed_for_link)

**HTTP 400** · client error · not retryable

a caller-supplied slug is not allowed with visibility ‘link’

**Hint.** either drop visibility ‘link’ (new apps default to private, which accepts an owner-chosen slug) or omit -<!-- -->-slug to let the relay generate an unguessable link slug

**Remediation.** Link-visibility slugs are always server-generated and unguessable. Drop visibility `link` (new apps default to private, which accepts your slug), or omit `--slug` to let the relay mint the link slug.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## slug\_taken

[Section titled “slug\_taken”](#slug_taken)

**HTTP 409** · client error · not retryable

slug ‘\<slug>’ is already in use

**Hint.** choose a different -<!-- -->-slug, or omit it to let the relay generate one

**Remediation.** Another app already uses that slug. Choose a different `--slug`, or omit it and let the relay generate an unused one.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## soft\_deleted

[Section titled “soft\_deleted”](#soft_deleted)

**HTTP 410** · client error · not retryable

\<entity> is in trash

**Hint.** restore the \<entity> from trash (POST /v1/trash/\<entity>s/:id/restore) before mutating it, or use ?include\_deleted=true on read-only endpoints to see its current state

**Remediation.** The row is in trash and recoverable until the sweeper reclaims it. Restore it (`POST /v1/trash/<entity>s/:id/restore`) before mutating, or pass `?include_deleted=true` on read-only endpoints to inspect it.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## too\_many\_collections

[Section titled “too\_many\_collections”](#too_many_collections)

**HTTP 400** · client error · not retryable

manifest declares 99 collections, exceeding the limit of 50

**Hint.** reduce the number of declared collections, or ask the operator to raise MAX\_COLLECTIONS\_PER\_APP

**Remediation.** Declare fewer collections, or ask the operator to raise `MAX_COLLECTIONS_PER_APP`. Consider whether some collections can merge into one with a discriminator field.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## too\_many\_embeds

[Section titled “too\_many\_embeds”](#too_many_embeds)

**HTTP 400** · client error · not retryable

manifest declares 99 embeds entries, exceeding the limit of 50

**Hint.** reduce the number of embeds entries, or ask the operator to raise MAX\_EMBEDS

**Remediation.** List fewer `embeds`, or ask the operator to raise `MAX_EMBEDS`. Only origins you iframe need to be declared.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## too\_many\_external\_hosts

[Section titled “too\_many\_external\_hosts”](#too_many_external_hosts)

**HTTP 400** · client error · not retryable

manifest declares 99 externalHosts entries, exceeding the limit of 50

**Hint.** reduce the number of externalHosts entries, or ask the operator to raise MAX\_EXTERNAL\_HOSTS

**Remediation.** List fewer `externalHosts`, or ask the operator to raise `MAX_EXTERNAL_HOSTS`. Only origins your page actually fetches from need to be declared.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## unauthorized

[Section titled “unauthorized”](#unauthorized)

**HTTP 401** · client error · not retryable

**Hint.** the request needs a valid bearer token: an agent API key for /v1 endpoints, or a participant token for /s endpoints

**Remediation.** Attach a valid bearer token. For `/v1` agent endpoints send your agent API key (register once with `homespun agent register`); for `/s` participant endpoints send the participant token the app minted. A missing or mistyped `Authorization` header is the usual cause.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## unique\_backfill\_conflict

[Section titled “unique\_backfill\_conflict”](#unique_backfill_conflict)

**HTTP 409** · client error · not retryable

cannot add a unique constraint on ‘\<field>’ to collection ‘\<collection>’: two or more existing live rows already share a value for ‘\<field>’

**Hint.** resolve the existing duplicates first: delete or edit the colliding rows so every live row holds a distinct ‘\<field>’ value (compared after trimming and case-folding), then redeploy with ‘\<field>’ in the collection’s ‘unique’ list

**Remediation.** Adding `unique` to a collection that already holds duplicate values for that field is refused, so the constraint is never half-applied. Find the live rows that share a value (compared after trimming and case-folding), delete or edit all but one so every live row holds a distinct value, then redeploy with the field in `unique`.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## unique\_conflict

[Section titled “unique\_conflict”](#unique_conflict)

**HTTP 409** · client error · not retryable

a row with this ‘\<field>’ already exists in collection ‘\<collection>’

**Hint.** ‘\<field>’ is declared unique on this collection; use a different value, or upsert on ‘\<field>’ (POST with { on: ‘\<field>’, data }) to update the existing row instead of creating a duplicate

**Remediation.** The collection declares this field as `unique`, and another live row already holds this value (values are compared after trimming and case-folding). Use a different value, or upsert on this field (`--on <field>`) to update the existing row in place instead of creating a duplicate.

**See also:** [CLI reference](https://docs.homespun.dev/agents/cli-reference/)

## unknown\_event\_type

[Section titled “unknown\_event\_type”](#unknown_event_type)

**HTTP 422** · client error · not retryable

**Hint.** the event does not satisfy the app’s event schema; check the event type and payload against the declared schema

**Remediation.** The event type is not one the app schema declares. Send an event whose type matches the declared schema, or widen the schema to cover it.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)

## upload\_forbidden

[Section titled “upload\_forbidden”](#upload_forbidden)

**HTTP 403** · client error · not retryable

**Hint.** this identity may not upload to this app

**Remediation.** This identity may not upload to this app. Confirm you are the owner or owning agent, and that the app permits uploads for your role.

**See also:** [Agent quickstart](https://docs.homespun.dev/agents/quickstart/)

## webhook\_invalid

[Section titled “webhook\_invalid”](#webhook_invalid)

**HTTP 400** · client error · not retryable

a webhooks rule is malformed

**Hint.** check the named webhooks rule field against the x-homespun-manifest.webhooks grammar (on ∈ {create,update}; collection must be declared; when is an optional level/edge condition; url must be a public https target with no userinfo and no IP literal)

**Remediation.** Fix the webhooks rule field named in the message. `on` is create or update, `collection` must be declared, and `url` must be a public https target with no userinfo and no IP literal. `when` is an optional level or edge condition.

**See also:** [Manifest reference](https://docs.homespun.dev/agents/manifest-reference/)
