Reference
Errors
Error response format and common status codes.
For agents: Parse
error.codeanderror.message, report both, and use events for account-visible runtime detail.
Shape
{
"error": {
"code": "invalid_path",
"message": "Release path must be relative."
}
}
Common statuses are 400, 401, 402, 403, 404, 409, 410, 413, 429, 451, and 502.
402 means the request is valid, but the selected account plan does not include the requested feature or limit. Entitlement errors use entitlement_required or plan_limit_exceeded and include details such as plan_key, required_plan_key, feature_key, limit_key, allowed, and violations.
403 means the authenticated actor is associated with the app’s platform account but their account role cannot perform the operation. For example, viewers can read account apps but cannot write secrets or create app-user invites. 404 is used when an app or account should not be revealed to a non-member.
App-user roles declared in manifest.userland.json are runtime roles only. They do not satisfy platform account authorization for publish, secrets, rollback, events, or invites.
Common Codes
invalid_path: a release file path is absolute, contains.., or targets_userland/.missing_static_root:runtime.static_rootdoes not match any published file.missing_server_entry:runtime.server_entrydoes not match a published server file.invalid_resource_manifest: resource declarations failed validation.entitlement_required: the manifest or operation requires a higher plan feature.plan_limit_exceeded: the operation would exceed an account, manifest, or usage limit.billing_restricted: account billing state blocks the requested premium operation.quota_exceeded: a usage quota blocks the narrow operation causing the overage.abuse_throttled: free-plan or abuse-control rate limiting blocked the request.account_suspended: account-level abuse, security, or legal flag blocks mutation or serving.app_suspended: app-level abuse or security flag blocks mutation or serving.app_takedown: app content is unavailable due to legal takedown.route_disabled: slug or custom-domain route is pending, disabled, or deleted.downgrade_incompatible: requested downgrade cannot proceed until incompatible apps, routes, or features are remediated.domain_pending_verification: custom domain cannot become active until ownership or certificate verification completes.auth_disabled: app-user auth is not enabled for the app.invalid_role: an app-user invite requested a role not declared by the app.pending_secrets: activation is blocked until required app secrets are set.requires_migration: durable resource changes need an explicit migration plan.invalid_email_auth_token: console email signin link is invalid, expired, used, or revoked.invalid_pending_signup: pending passwordless signup cookie is missing, expired, used, or revoked.email_already_registered: pending signup email already belongs to a platform user.username_taken: requested platform username is already taken.invalid_device_authorization: CLI device code or user code is invalid, expired, used, or revoked.device_authorization_expired: pending CLI device approval expired before authorization.password_auth_disabled: legacy platform password auth endpoint is disabled for launch.password_signup_disabled: legacy public username/password signup endpoint is disabled for launch.
Auth States
Userland platform auth is passwordless. Console signin uses email links, CLI signin uses browser-approved device authorization, and API access uses API keys.
POST /v0/auth/token, POST /v0/platform/sessions, password reset request/confirm, and unauthenticated POST /v0/accounts intentionally return 410 during the transition. There is no platform password reset flow.
Device polling can return authorization_pending, slow_down, denied, expired, or consumed. Respect slow_down.interval; do not start a new device flow unless the current one is denied, expired, or consumed.
Recovery
Use the CLI to inspect and recover:
userland apps events "$APP_ID" --limit 25
userland apps releases "$APP_ID"
userland apps rollback "$APP_ID" "$RELEASE_ID"
See /guides/troubleshooting for the full debug path.