zynactradocs

Errors

Error codes, HTTP statuses, deny reasons and validation fields, the same in Go, TypeScript and the HTTP API.

Codes

CodeHTTPTitleWhen
denied403ForbiddenA decision denied; reason says why.
escalation403Not allowed to grant thisAn admin action beyond the caller's reach, or assigning themselves.
invalid400Invalid requestBad input. Validation problems name the field. In strict mode, also unknown permissions and invalid resources.
not_found404Not found
conflict409ConflictThe last access admin, an already revoked assignment, a role in use, a duplicate key or mapping.
unavailable503Authorization unavailableCerbos, the store or the resolver failed. Checks treat it as a denial.

Anything else a handler passes to accesshttp.WriteError becomes a 500 with no detail; internals never reach the response.

Deny reasons

Set on denied. Record checks report no_grant or policy; Explain (reason on the Explanation) reports the finer other_org, scope, condition and org_rule.

Reason
no_grantThey hold the permission at no scope.
policyCerbos denied this record.
other_orgThe record belongs to another org.
scopeHeld, but the record is outside every scope it's held at.
conditionIn scope, but the action's condition is false.
org_ruleAn org rule denied it; Explain names the rule.
unknown_permissionNot in the manifest.
invalid_resourceMissing or extra attributes, a wrong type, a value outside an enum, the wrong kind.
unavailableAn outage, turned into a denial by Assert / assert.
no_subjectNo subject on the request.

Nest adds two of its own: 403 undeclared_route for a route with no access decorator, and 500 unchecked_requirement (both SDKs, strict mode) for a guarded route that never checked its permission against a record.

Validation fields

Admin validation problems carry field, the request field they're about, so forms show them at the input: userId, roleId, scopeType, scopeIds, validFrom, validUntil, reason, key, name, permissions, groupName.

In code

var e *access.Error // Code, Reason, Permission, Field, Message, CallID
if errors.As(err, &e) && e.Code == access.CodeDenied { ... }

access.ErrorCode(err)  // the Code, or "" for other errors
access.IsDenied(err)   // a denial?
accesshttp.WriteError(w, err)
import { AccessError } from "@zynactra/access";

if (err instanceof AccessError && err.code === "denied") { ... }   // code, reason, permission, field
throw new AccessError({ code: "not_found", message: "leave request not found" });

In React, the client throws AccessApiError with status, code, reason, permission, field and the full problem.

An access error is a denial: never catch one and continue.

Edit on GitHub

On this page