Skip to content

Errors and HTTP statuses

Test for errors with errors.Is. wardn.HTTPStatus(err) gives the status code to return.

Error Meaning Status
ErrUnauthenticated No signed-in user: middleware found no user, or a guarded call had none in ctx. 401
ErrDenied (a *DeniedError) The user lacks the permission. The error carries the decisions. 403
ErrEscalation The escalation guard refused: the actor doesn’t hold a permission they tried to grant, remove or restrict. 403
ErrInvalidInput A malformed ID, name, permission, time window or cursor. 400
ErrNotAssignable The role can’t be assigned at that scope (assignable_at, or outside a custom role’s owner). 400
ErrRoleNotFound No such custom role, or one the actor may not manage (deliberately indistinguishable). 404
ErrConflict The role was changed by someone else since it was read. 409
ErrRoleNameTaken A role with a name that reads the same already exists here. 409
ErrRoleInUse Deleting a role that is still assigned, without Cascade(). 409
ErrAlreadyLinked Link to a different parent than the scope already has; usually two tenants reusing an ID. Use Move to move on purpose. 409
ErrInvalidLink A link contradicts the scope tree, or stored data does. 500
ErrNoTransaction A change had only one of store.WithTx and w.Transaction in its context; it needs both (store.RunInTx adds both). See your own transaction. 500
ErrLinksExternal Link was called while Config.ParentOf is set. 500
ErrAuditRejected OnChange returned an error, so the change wasn’t made. 500
ErrCacheInvalidation The change was saved, but the cache couldn’t be invalidated afterwards. Retrying is safe. 500
*UndefinedError An undefined permission, role or scope type, with a suggestion. 500
*PolicyError Problems in the policy, each with a line and a suggestion. — (at startup)

Messages are written for the developer who caused them

Section titled “Messages are written for the developer who caused them”
wardn: permission "loan:aprove" is not defined; did you mean "loan:approve"?
wardn: role is not assignable at this scope: role "teller" cannot be assigned at organisation:acme; it is assignable at: branch
wardn: invalid scope link: cannot link branch:lagos to organisation:acme; a branch's parent must be a region
wardn: you cannot grant permissions you do not hold: "report:export" at branch:lagos

wardn’s middleware never puts these messages in responses. Clients see a generic body, such as {"error":"forbidden"}. The detail goes to OnDecision and to your OnError handler.

Questions about this page?

Ask below, point out something wrong or unclear, or suggest an improvement. Reading needs no account; to post, sign in with GitHub.