ImageKit Custom Error Types: ParseColorError and ParseWatermarkPositionError Explained

ImageKit defines two custom error types, ParseColorError and ParseWatermarkPositionError, in src/errors.rs to handle invalid hexadecimal color codes and watermark placement strings with precise, user-friendly error messages.

The hzbd/imagekit Rust crate provides CLI tools for image processing that require strict input validation for parameters like overlay colors and watermark positions. To surface clear validation failures without cluttering the business logic, the codebase implements custom error types using the thiserror crate, enabling ergonomic error propagation throughout the application.

Custom Error Types Defined in ImageKit

Located in [src/errors.rs](https://github.com/hzbd/imagekit/blob/master/src/errors.rs), ImageKit's custom error types are thin wrapper structs around String values that leverage procedural macros for automatic trait implementation.

ParseWatermarkPositionError

The ParseWatermarkPositionError type validates watermark placement arguments against a strict whitelist of positional keywords. According to the source code at lines 5‑6, it rejects any string that does not match the valid options: nw, north, ne, west, center, east, sw, south, or se.

#[derive(Debug, Error)]
#[error("Invalid watermark position: '{0}'. Valid options are: nw, north, ne, west, center, east, sw, south, se")]
pub struct ParseWatermarkPositionError(pub String);

ParseColorError

The ParseColorError type enforces hexadecimal color code formatting rules as implemented at lines 9‑10 of src/errors.rs. It validates that color strings contain exactly 6 or 8 hexadecimal digits, optionally prefixed with a hash symbol.

#[derive(Debug, Error)]
#[error("Invalid hex color code: '{0}'. Must be in RRGGBB or RRGGBBAA format.")]
pub struct ParseColorError(pub String);

Both structs derive Debug and Error via thiserror, which automatically implements std::error::Error and generates the display format specified in the #[error(...)] attribute.

How ImageKit Implements Input Validation with Custom Errors

The custom error types integrate directly into the CLI argument parsing logic in [src/cli.rs](https://github.com/hzbd/imagekit/blob/master/src/cli.rs), specifically within FromStr trait implementations.

HexColor Parsing

Lines 56‑62 implement FromStr for the HexColor struct, returning ParseColorError when input strings fail length validation or hexadecimal conversion:

// Conceptual implementation based on src/cli.rs lines 56-62
impl FromStr for HexColor {
    type Err = ParseColorError;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // Validation logic that returns ParseColorError on failure
        // ...
    }
}

WatermarkPosition Parsing

Similarly, lines 84‑89 handle WatermarkPosition parsing, mapping unknown keywords to ParseWatermarkPositionError:

// Conceptual implementation based on src/cli.rs lines 84-89
impl FromStr for WatermarkPosition {
    type Err = ParseWatermarkPositionError;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // Match against valid positions or return ParseWatermarkPositionError
        // ...
    }
}

This architecture isolates validation concerns into dedicated types, allowing functions to propagate Result<_, Parse*Error> without manual error message construction.

Practical Examples of Handling ImageKit Custom Errors

When building tools atop the imagekit crate, you can leverage these error types to provide precise feedback to end-users.

Validating Hex Color Input

This example demonstrates catching ParseColorError when parsing CLI arguments:

use imagekit::cli::HexColor;
use std::str::FromStr;

fn parse_user_color(input: &str) {
    match HexColor::from_str(input) {
        Ok(color) => println!("Parsed RGBA: {:?}", color.0),
        Err(e) => eprintln!("Error: {}", e), 
        // Output: "Invalid hex color code: 'zzzzzz'. Must be in RRGGBB or RRGGBBAA format."
    }
}

// Usage
parse_user_color("#ff00ff");  // Success
parse_user_color("12345");    // Fails - too short
parse_user_color("gggggg");   // Fails - invalid hex

Validating Watermark Position

The following pattern handles invalid placement strings via ParseWatermarkPositionError:

use imagekit::cli::WatermarkPosition;
use std::str::FromStr;

fn set_watermark(position_arg: &str) {
    match WatermarkPosition::from_str(position_arg) {
        Ok(pos) => println!("Placing watermark at: {}", pos),
        Err(e) => eprintln!("Configuration error: {}", e),
        // Output: "Invalid watermark position: 'middle'. Valid options are: nw, north, ne..."
    }
}

// Usage
set_watermark("se");      // Success - southeast
set_watermark("center");  // Success
set_watermark("middle");  // Fails - invalid keyword

Summary

ImageKit's custom error types provide a robust mechanism for input validation in its CLI tooling:

  • ParseColorError in src/errors.rs validates hexadecimal color strings against RRGGBB or RRGGBBAA formats
  • ParseWatermarkPositionError enforces strict watermark placement keywords across nine valid positions
  • Both types use the thiserror crate to derive std::error::Error with formatted error messages
  • The errors integrate with FromStr implementations in src/cli.rs (lines 56‑62 and 84‑89) for ergonomic parsing
  • This pattern enables precise error propagation without scattering validation logic throughout the codebase

Frequently Asked Questions

How does ImageKit validate hexadecimal color codes?

ImageKit validates hex colors through the ParseColorError type defined in src/errors.rs. The validation requires strings to contain exactly 6 or 8 hexadecimal digits, optionally prefixed with #. When HexColor::from_str() encounters malformed input in src/cli.rs (lines 56‑62), it returns this error type with a message specifying the invalid input and required format.

What watermark positions are valid in ImageKit?

According to the ParseWatermarkPositionError definition at lines 5‑6 of src/errors.rs, ImageKit accepts nine specific keywords for watermark placement: nw, north, ne, west, center, east, sw, south, and se. Any other string passed to WatermarkPosition::from_str() (implemented at lines 84‑89 of src/cli.rs) triggers the custom error with a complete list of valid options.

Why does ImageKit use the thiserror crate for custom errors?

The thiserror crate reduces boilerplate by automatically deriving the std::error::Error trait and implementing Display based on the #[error(...)] attribute. For ImageKit's ParseColorError and ParseWatermarkPositionError, this eliminates manual error message formatting code while preserving the ability to wrap the original invalid input string for debugging purposes.

Can I use ImageKit's error types in my own Rust application?

Yes, if you depend on the imagekit crate, you can import ParseColorError and ParseWatermarkPositionError from the library to handle validation in your own CLI tools or image processing pipelines. These types implement std::error::Error, making them compatible with Rust's ecosystem error handling patterns like the ? operator and error conversion traits.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →