Error State
Placeholder shown when something failed to load or submit — page-level errors, network retries, and form-level error summaries.
Page-level error
For a whole page or panel that failed to render. Pairs a clear cause-free message (the error wasn't the user's fault) with two ways forward: retry in place, or leave entirely. Always offer both — a retry-only error traps anyone hitting a hard failure.
500 — Something went wrong
The page failed to load on our end. It's not something you did — try again in a moment.
<div class="hero bg-base-100 rounded-[var(--radius-sm)] py-16">
<div class="hero-content text-center">
<div class="max-w-sm">
<i data-lucide="server-crash" class="mx-auto mb-4 size-12 text-error/60"></i>
<h3 class="text-lg font-semibold">500 — Something went wrong</h3>
<p class="py-3 text-base-content/60">
The page failed to load on our end. It's not something you did —
try again in a moment.
</p>
<div class="flex justify-center gap-2">
<button class="btn btn-primary btn-sm">Try again</button>
<a href="#" class="btn btn-ghost btn-sm">Go to homepage</a>
</div>
</div>
</div>
</div>
Network error retry
Smaller footprint than the full page-level variant — for a widget, panel, or single request that failed inside an otherwise-working page. The retry button shows its own loading state so a slow connection doesn't read as a second failure.
Couldn't reach the server
Check your connection and try again.
<div class="text-center py-12 px-4">
<i data-lucide="wifi-off" class="mx-auto mb-3 size-9 text-error/60"></i>
<h3 class="font-semibold">Couldn't reach the server</h3>
<p class="text-sm text-base-content/60 mt-1">
Check your connection and try again.
</p>
<button class="btn btn-outline btn-error btn-sm mt-4">
<i data-lucide="refresh-cw" class="size-4"></i>
Retry
</button>
</div>
Form-level error summary
Sits at the top of a form to list every validation failure at
once, so a long form doesn't make the user hunt field-by-field
for what's wrong. Uses DaisyUI's alert rather than
a custom banner — severity-coded blocks are exactly what
alert is for.
3 fields need your attention
- Email address is invalid
- Password must be at least 8 characters
- You must accept the terms to continue
<div role="alert" class="alert alert-error alert-soft">
<i data-lucide="circle-alert" class="size-5 shrink-0"></i>
<div>
<p class="font-medium">3 fields need your attention</p>
<ul class="text-sm mt-1 list-disc list-inside opacity-90">
<li>Email address is invalid</li>
<li>Password must be at least 8 characters</li>
<li>You must accept the terms to continue</li>
</ul>
</div>
</div>
Inline field error
The smallest unit of error state — attached directly to the
input that failed. Uses DaisyUI's input-error
modifier rather than a custom border color, so it stays in
sync with whatever theme colors the builder is using.
<label class="form-control w-full max-w-xs">
<span class="label-text mb-1">Email</span>
<input type="email" value="not-an-email" class="input input-error w-full" />
<span class="text-error text-xs mt-1 flex items-center gap-1">
<i data-lucide="circle-alert" class="size-3.5"></i>
Enter a valid email address
</span>
</label>
Pick the variant that matches the failure's blast radius: a whole page that can't render needs the page-level variant with an escape route, a single failed request needs the smaller retry variant, and form problems belong with the form — either summarized at the top for long forms, or inline for a single field. Don't reach for the page-level variant just because an error "feels serious"; a failed save inside an otherwise-working page is still a small-footprint failure.