Error Dialog
The ErrorDialog component displays error messages in a Bootstrap modal, perfect for inline errors that don't require a full page reload. It supports retry actions, HTMX out-of-band swaps, and backend error messages.
Goal
By the end of this guide, you'll be able to show beautiful error modals for AJAX failures, validation errors, and backend exceptions without writing any JavaScript.
Quick Start
Here's the simplest way to show an error dialog.
Visual Examples & Use Cases
1. Variants
Different severity levels for different errors.
Failed to save changes
Your session will expire in 5 minutes
This feature is currently in beta
2. With Retry Action
Let users retry failed operations.
ErrorDialog(
message="Network timeout. Please try again.",
retry_url="/api/save",
retry_text="Retry",
modal_id="network-error"
)
Practical Functionality
HTMX Integration
Show errors from HTMX requests.
@app.post("/profile/save")
def save_profile(req):
try:
update_profile(req.form)
return Div("Profile saved!", cls="alert alert-success")
except ValidationError as e:
# Return error dialog via HTMX
return ErrorDialog(
message=str(e),
title="Validation Error",
variant="warning"
)
except Exception as e:
return ErrorDialog(
message="Failed to save profile. Please try again.",
retry_url="/profile/save",
retry_text="Try Again"
)
Out-of-Band Swaps
Show error dialog while updating other content.
@app.post("/cart/add")
def add_to_cart(product_id: int):
try:
cart.add(product_id)
# Return updated cart + success message
return Div(
CartWidget(cart),
Toast("Added to cart!", variant="success", hx_swap_oob="true")
)
except OutOfStockError:
# Return cart + error dialog
return Div(
CartWidget(cart),
ErrorDialog(
message="This item is out of stock",
modal_id="stock-error",
hx_swap_oob="true",
show=True # Show immediately
)
)
Backend Error Messages
Display backend exceptions to users.
@app.post("/api/process")
def process_data(req):
try:
result = expensive_operation(req.form)
return result
except DatabaseError as e:
# Show technical error in development
if app.debug:
return ErrorDialog(
message=f"Database error: {e}",
title="Database Error"
)
else:
# Show user-friendly error in production
return ErrorDialog(
message="Unable to process your request. Our team has been notified.",
retry_url="/api/process"
)
Integration Patterns
With Form Validation
@app.post("/register")
def register(req):
email = req.form.get("email")
password = req.form.get("password")
# Validate
if not email or "@" not in email:
return ErrorDialog(
message="Please enter a valid email address",
title="Validation Error",
variant="warning",
modal_id="validation-error",
show=True
)
if len(password) < 8:
return ErrorDialog(
message="Password must be at least 8 characters",
title="Validation Error",
variant="warning",
show=True
)
# Create user
create_user(email, password)
return hx_redirect("/dashboard")
With Confirmation Dialogs
Combine with retry for dangerous actions.
@app.delete("/account")
def delete_account(req):
user = req.session.get("user")
try:
delete_user(user.id)
return hx_redirect("/goodbye")
except Exception as e:
return ErrorDialog(
message="Failed to delete account. Please contact support if this persists.",
title="Deletion Failed",
retry_url="/account/delete",
retry_text="Try Again"
)
Auto-Show on Load
Show error immediately when page loads.
@app.get("/checkout")
def checkout(req):
cart = get_cart(req)
if cart.is_empty():
# Show error dialog on page load
return Container(
H1("Checkout"),
ErrorDialog(
message="Your cart is empty",
title="Cannot Checkout",
variant="warning",
show=True, # Auto-show
modal_id="empty-cart"
)
)
return CheckoutPage(cart)
Parameter Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
message |
str |
Required | Error message to display |
title |
str |
"Error" | Modal title |
variant |
str |
"danger" | Color variant (danger, warning, info) |
modal_id |
str |
"error-dialog" | Unique modal ID |
retry_url |
str \| None |
None |
URL for retry button (None to hide) |
retry_text |
str |
"Retry" | Text for retry button |
show |
bool |
False |
Whether to show modal immediately |
**kwargs |
Any |
- | Additional HTML attributes |
Best Practices
✅ Do This
# Use appropriate variants
ErrorDialog(message="Invalid input", variant="warning")
ErrorDialog(message="Server error", variant="danger")
ErrorDialog(message="Feature unavailable", variant="info")
# Provide retry for transient errors
ErrorDialog(
message="Network timeout",
retry_url="/api/save",
retry_text="Try Again"
)
# Use unique IDs for multiple dialogs
ErrorDialog(message="Error 1", modal_id="error-1")
ErrorDialog(message="Error 2", modal_id="error-2")
❌ Don't Do This
# Don't expose sensitive errors in production
ErrorDialog(message=str(database_connection_string))
# Don't use wrong variants
ErrorDialog(message="Success!", variant="danger") # Use Toast instead
# Don't reuse modal IDs
ErrorDialog(message="Error 1", modal_id="error")
ErrorDialog(message="Error 2", modal_id="error") # Conflict!
faststrap.components.feedback.error_dialog.ErrorDialog(message, title='Error', variant=None, modal_id='error-dialog', retry_url=None, retry_text='Retry', close_text='Close', show=True, **kwargs)
Modal/dialog variant for inline error display.
Shows error messages from backend or client-side validation in a modal dialog. Supports retry actions and custom styling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Error message to display (can be from backend) |
required |
title
|
str
|
Dialog title |
'Error'
|
variant
|
VariantType | None
|
Bootstrap variant for styling (danger, warning, info) |
None
|
modal_id
|
str
|
Unique ID for the modal |
'error-dialog'
|
retry_url
|
str | None
|
Optional URL to retry the failed action (shows retry button) |
None
|
retry_text
|
str
|
Text for retry button |
'Retry'
|
close_text
|
str
|
Text for close button |
'Close'
|
show
|
bool
|
Whether to show modal immediately |
True
|
**kwargs
|
Any
|
Additional HTML attributes |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Modal component with error content |
Example
Basic error dialog:
ErrorDialog(message="Failed to save record")
Backend error with retry:
ErrorDialog( ... message="Network timeout. Please try again.", ... retry_url="/api/save", ... retry_text="Try Again" ... )
Custom variant and title:
ErrorDialog( ... message="This action requires premium access", ... title="Access Restricted", ... variant="warning", ... retry_url="/pricing", ... retry_text="Upgrade Now" ... )
HTMX integration (show on error):
@app.post("/save") def save(req): try: # ... save logic ... return Card("Success!") except Exception as e: return ErrorDialog( message=str(e), modal_id="save-error", hx_swap_oob="true" )
Note
For full-page errors, use ErrorPage instead.
The dialog can be triggered via HTMX out-of-band swaps:
# Server returns error dialog alongside main content
return (main_content, ErrorDialog(message="Error", hx_swap_oob="true"))
Or shown programmatically with Bootstrap's modal API:
Source code in src/faststrap/components/feedback/error_dialog.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |