Error Handling
PolicyError for invalid configuration or evaluation failures in permit.
PolicyError signals invalid configuration or evaluation failures. permit keeps error handling minimal by design: permission checks resolve to false instead of throwing. This page covers the PolicyError class and when the library throws it.
When permit Throws (and When It Doesn’t)
createPolicy()throws aPolicyErrorat creation time if a resource key has no schema ("Missing schema for resource: <name>").policy.can()never throws. Malformed permission strings, unlisted actions, resources that fail schema validation, missing rules, and rules that throw all resolve tofalse. Rule and validation errors are logged withconsole.warn.
PolicyError
The PolicyError class is a custom error type for policy-related failures. The library uses it for configuration errors, and you can throw it yourself to distinguish authorization errors from other application errors.
import { PolicyError } from "@zap-studio/permit";
Constructor
new PolicyError(message: string)
Properties
| Property | Type | Description |
|---|---|---|
name |
string |
Always "PolicyError" |
message |
string |
Error description |
stack |
string |
Stack trace (inherited) |
PolicyError extends Error, so instanceof Error checks also match it.
Throwing Policy Errors
import { PolicyError } from "@zap-studio/permit";
// Throw when an authorization check fails
throw new PolicyError("User is not authorized to delete this resource");
// Throw for invalid policy configuration
throw new PolicyError("Unknown resource type: 'invalid'");
// Throw for missing context
throw new PolicyError("User context is required for this action");
Catching Policy Errors
import { PolicyError } from "@zap-studio/permit";
async function deletePost(postId: string, context: AppContext) {
try {
const post = await getPost(postId);
if (!(await policy.can(context, "post:delete", post))) {
throw new PolicyError("Not authorized to delete this post");
}
await db.posts.delete(postId);
return { success: true };
} catch (error) {
if (error instanceof PolicyError) {
// Handle authorization errors
return { success: false, error: error.message, code: "FORBIDDEN" };
}
// Re-throw unexpected errors
throw error;
}
}
Best Practices
- Use
PolicyErrorfor authorization failures — Makes it easy to distinguish from other errors - Catch errors at boundaries — Handle
PolicyErrorin middleware or API handlers - Include context in error messages — “Not authorized to delete post-123” is better than “Forbidden”
- Log denied attempts — Track authorization failures for security monitoring