Access Denied With Request Path

Error 403

You are signed in, but not into this

This record sits behind the clinical role, which your account does not currently hold. Asking for it takes one click and goes to whoever owns the record.

Who can grant this

Portrait of Elena Rourke

Elena Rourke

Practice lead, Bramble Health

Portrait of Priya Nandan

Priya Nandan

Records administrator

Whether the answer is yes or no, the decision and its timestamp are written into the audit log.

Deep green gradient backdrop

Access request

Your request goes to the record owner, not a shared inbox

About this block

Access Denied With Request PathPRO

A permissions error that names the missing role, lists the people who can grant it with their portraits, and floats a live access request card on an image tile beside the copy.

Error37: Access Denied With Request Path

A permissions error that names the missing role, lists the people who can grant it with their portraits, and floats a live access request card on an image tile beside the copy.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/error37?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/error37?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/error37.tsx, the notification20 request piece it floats on the tile (installed to components/beste/piece/notification20.tsx), and the button21 component it uses for the actions.

Quick start

The installed file exports error37Demo alongside the block: the exact props behind the preview above. Spread it to get a working error page in one line.

tsx
import { Error37, error37Demo } from "@/components/beste/block/error37";

export default function ForbiddenPage() {
  return <Error37 {...error37Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Error37 } from "@/components/beste/block/error37";
import { Notification20 } from "@/components/beste/piece/notification20";
import { ShieldCheck } from "lucide-react";

export default function ForbiddenPage() {
  return (
    <Error37
      code="Error 403"
      heading="You are signed in, but not into this"
      description="This record sits behind the clinical role, which your account does not hold."
      buttons={[
        { label: "Request access", href: "/access/request" },
        { label: "Back to the workspace", href: "/app" },
      ]}
      media={
        <Notification20
          icon={ShieldCheck}
          title="Access request"
          meta="Your request goes to the record owner"
          primaryLabel="Send request"
          secondaryLabel="Cancel"
        />
      }
      image={{ src: "/backdrops/green.jpg", alt: "Deep green gradient backdrop" }}
      approversLabel="Who can grant this"
      approvers={[
        {
          name: "Elena Rourke",
          role: "Practice lead, Bramble Health",
          avatar: { src: "/people/elena.jpg", alt: "Portrait of Elena Rourke" },
        },
      ]}
      footnote="The decision and its timestamp are written into the audit log."
    />
  );
}

Props

PropTypeDefaultDescription
codestring–Small status line above the heading
headingstring–Error heading, rendered as the page h1
descriptionstring–Supporting paragraph, capped at max-w-md
buttonsActionLink[][]Actions in source order, first solid and the rest outlined
mediaReactNode–Live asset on the tile, notification20 in the demo
image{ src: string; alt: string }–Backdrop behind the media tile
approversLabelstring–Small label above the approver list
approversApprover[][]People who can grant the missing role
footnotestring–Audit note under the approvers
classNamestring–Extra classes for the outer section
ts
type ActionLink = {
  label: string;
  href: string;
};

type Approver = {
  name: string;
  role: string;
  avatar: { src: string; alt: string };
};

Behavior notes

  • Naming the approvers is the point of the block. A 403 that says only "access denied" sends people to a shared inbox, so this one carries the specific people who can act, populated from whoever owns the record.
  • Approver rows use min-w-0 with truncate on both lines, so a long name or role ellipsizes rather than pushing the portrait out of the row.
  • Portraits are fixed at size-10 with shrink-0, so the row height stays constant however long the text is.
  • Button tones are positional and not overridable: the first is primary, later ones are outline.
  • The approver group carries a border-t on its own container, so removing approvers removes the rule with it rather than leaving a stray divider.
  • The request card in the tile is presentational. This block renders no form and sends no request, so the primary action is a link to wherever your request flow lives.
  • The layout is lg:grid-cols-2 with lg:items-center, so the tile stays centered against a copy column whose height varies with the number of approvers.

More Error blocks

View all Error
PRO

error16

403 Access Request

PRO

error23

Invitation Only Access

FREE

error9

404 Did You Mean

Get Pro access