Skip to content
Zap Studio
permit
Esc
navigateopen⌘Jpreview
On this page

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 a PolicyError at 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 to false. Rule and validation errors are logged with console.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

  1. Use PolicyError for authorization failures — Makes it easy to distinguish from other errors
  2. Catch errors at boundaries — Handle PolicyError in middleware or API handlers
  3. Include context in error messages — “Not authorized to delete post-123” is better than “Forbidden”
  4. Log denied attempts — Track authorization failures for security monitoring

Last updated on September 15, 2026

Was this page helpful?