Backend Error Handling
Relevant source files
The following files were used as context for generating this wiki page:The hdrify application employs a straightforward and robust error handling strategy on its Rust backend. Instead of letting errors cause panics or return non-200 HTTP status codes for application-level failures, it captures all potential failures during image processing and communicates them to the frontend via a unified JSON response structure. This ensures a consistent communication protocol and allows the frontend to gracefully display user-friendly error messages.
All backend logic for handling uploads and errors is contained within the handle_upload function. The web server, built with warp, routes all POST requests from the /upload endpoint to this function. The function is designed to never be rejected by warp for processing errors; instead, it always returns a Result<impl warp::Reply, warp::Rejection> that resolves to an Ok(warp::reply::json(...)), effectively treating all outcomes as successful HTTP transactions containing a success or failure payload.
Sources: src/main.rs:16-134, Cargo.toml:7
Unified Response Model
The core of the error handling mechanism is the ProcessResponse struct. Every request to the /upload endpoint, whether successful or not, results in a JSON object serialized from this struct.
Sources: src/main.rs:8-13
ProcessResponse Struct
This diagram shows the structure of the ProcessResponse object.
Sources: src/main.rs:8-13
The fields of this struct are used to convey the outcome of the image processing task:
| Field | Type | Description |
|---|---|---|
success | bool | A boolean flag indicating if the image processing was successful. true for success, false for failure. |
message | String | A human-readable message describing the outcome. On failure, this contains the specific error details. |
image_data | Option<String> | An optional field containing the base64-encoded processed image data. It is Some on success and None on failure. |
Sources: src/main.rs:8-13
An example of an error response sent to the client:
{
"success": false,
"message": "File too large: 12.3MB. Maximum size is 10MB.",
"image_data": null
}
Sources: src/main.rs:52-58
Error Handling Flow
The handle_upload function follows a sequential validation and processing flow. If any step fails, it immediately constructs and returns a ProcessResponse with success: false and an appropriate error message, halting further execution.
This flowchart illustrates the decision points within the handle_upload function where errors can occur.
Sources: src/main.rs:16-134
Types of Backend Errors
The backend handles several categories of errors, primarily related to input validation and the external ImageMagick process.
Input Validation Errors
These checks occur before any significant processing begins.
| Check | Error Message | Source Location |
|---|---|---|
| Missing Image Data | "No image data provided" | src/main.rs:27-31 |
| File Size Exceeds 10MB | "File too large: {size}MB. Maximum size is 10MB." | src/main.rs:52-58 |
| Unsupported Image Format | "Unsupported image format. Please upload JPEG, PNG, or WebP images." | src/main.rs:64-70, 136-159 |
The frontend also performs similar validations for file size and type to provide immediate feedback, but the backend validation serves as the authoritative check.
Sources: src/main.rs:27-70, static/script.js:154-175
Processing Errors
These errors can occur during the image manipulation phase.
| Error Condition | Error Message | Source Location |
|---|---|---|
| Base64 Decoding Failure | "Failed to decode image: {error}" | src/main.rs:38-44 |
ImageMagick Command Execution | "Failed to execute ImageMagick: {error}" | src/main.rs:128-132 |
ImageMagick Process Failure | "ImageMagick error: {stderr_output}" | src/main.rs:119-124 |
| Reading Processed Image File | "Failed to read processed image: {error}" | src/main.rs:112-116 |
Sources: src/main.rs:38-44, src/main.rs:109-134
Frontend and Backend Interaction for Errors
The frontend JavaScript is designed to handle the unified response from the backend. It uses a single try...catch block to manage both network errors and application-level errors returned by the server.
This sequence diagram shows the communication flow when the backend reports an error.
Sources: src/main.rs:50-59, static/script.js:256-285
The frontend logic in script.js first checks if the fetch response itself is okay (e.g., not a 500 server error). Then, it parses the JSON and checks the result.success flag. If false, it calls the showError function with the message from the payload.
// static/script.js:275-282
if (result.success && result.image_data) {
// ... success logic ...
} else {
this.showError(result.message || 'Failed to process image');
this.fallbackToOriginal();
}
The showError function updates the content of the #errorMessage paragraph inside the #error div and makes it visible. The appearance of this error message is defined in static/style.css.
Sources: static/script.js:356-360, static/index.html:76-78, static/style.css:175-182
Summary
The backend error handling in hdrify is centralized and predictable. By capturing all potential failures and channeling them through a single ProcessResponse struct, the system provides a stable API contract. This allows the frontend to handle all application-level errors from a single code path, differentiating between success and failure based on a clear success flag in the JSON payload. This design simplifies client-side logic and ensures that users receive clear, actionable feedback for any issues encountered during the image processing workflow.
Sources: src/main.rs, static/script.js