Error Handling
compressionz uses a unified error type across all operations for consistent error handling.
Error Type
Section titled “Error Type”pub const Error = error{ InvalidData, ChecksumMismatch, OutputTooSmall, OutputTooLarge, UnexpectedEof, UnsupportedFeature, OutOfMemory, DictionaryMismatch, InvalidParameter,};Error Descriptions
Section titled “Error Descriptions”InvalidData
Section titled “InvalidData”The input data is corrupted, malformed, or not compressed with the specified codec.
Common causes:
- Data was modified after compression
- Wrong codec specified for decompression
- Truncated compressed data
- Random/uncompressed data passed to decompress
Example:
const result = cz.decompress(.zstd, random_data, allocator) catch |err| { if (err == error.InvalidData) { std.debug.print("Data is not valid Zstd compressed data\n", .{}); return; } return err;};Solutions:
- Verify you’re using the correct codec
- Check data wasn’t corrupted in transit/storage
- Use auto-detection:
cz.Codec.detect(data)
ChecksumMismatch
Section titled “ChecksumMismatch”Built-in checksum verification failed. Data integrity compromised.
Common causes:
- Data corruption during storage or transmission
- Partial/incomplete data
- Hardware errors (disk, memory)
Example:
const result = cz.decompress(.lz4, data, allocator) catch |err| { if (err == error.ChecksumMismatch) { std.debug.print("Data corrupted! Checksum verification failed.\n", .{}); // Request retransmission, restore from backup, etc. return error.DataCorruption; } return err;};Solutions:
- Re-fetch or restore data from source
- Check storage/network for errors
- Use checksums at application level too
Note: Only occurs for codecs with checksums: .lz4, .gzip, .zlib, .zstd
OutputTooSmall
Section titled “OutputTooSmall”Buffer provided to compressInto or decompressInto is too small.
Common causes:
- Pre-allocated buffer undersized
- Incorrect size calculation
Example:
var small_buffer: [100]u8 = undefined;
const result = cz.compressInto(.lz4, large_data, &small_buffer, .{}) catch |err| { if (err == error.OutputTooSmall) { // Allocate larger buffer const size = cz.maxCompressedSize(.lz4, large_data.len); const buffer = try allocator.alloc(u8, size); return cz.compressInto(.lz4, large_data, buffer, .{}); } return err;};Solutions:
- Use
maxCompressedSize()for compression buffers - Use known original size for decompression buffers
- Fall back to allocating API
OutputTooLarge
Section titled “OutputTooLarge”Decompressed size exceeds max_output_size limit.
Common causes:
- Decompression bomb (malicious data)
- Unexpectedly large legitimate data
- Limit set too low
Example:
const result = cz.decompressWithOptions(.gzip, untrusted_data, allocator, .{ .max_output_size = 10 * 1024 * 1024, // 10 MB limit}) catch |err| { if (err == error.OutputTooLarge) { std.debug.print("Decompressed size exceeds 10 MB limit\n", .{}); return error.SuspiciousInput; } return err;};Solutions:
- Increase limit if data is trusted
- Reject untrusted data that exceeds limits
- Stream process large data instead
UnexpectedEof
Section titled “UnexpectedEof”Compressed data ended unexpectedly. Input is truncated.
Common causes:
- Incomplete download/transfer
- File truncated
- Stream closed prematurely
Example:
const result = cz.decompress(.zstd, data, allocator) catch |err| { if (err == error.UnexpectedEof) { std.debug.print("Compressed data is incomplete\n", .{}); return error.IncompleteData; } return err;};Solutions:
- Verify complete data transfer
- Check file size matches expected
- Re-download/re-fetch data
UnsupportedFeature
Section titled “UnsupportedFeature”Requested feature not available for this codec.
Common causes:
- Zero-copy with codec that doesn’t support it
- Dictionary with codec that doesn’t support it
- Streaming with block-only codec
Example:
// Zstd doesn't support compressIntoconst result = cz.compressInto(.zstd, data, &buffer, .{}) catch |err| { if (err == error.UnsupportedFeature) { // Fall back to allocating version return cz.compress(.zstd, data, allocator); } return err;};Solutions:
- Check codec capabilities before using features
- Use fallback implementations
- Choose a different codec
// Check before usingif (codec.supportsDictionary()) { return cz.compressWithOptions(codec, data, allocator, .{ .dictionary = dict, });} else { return cz.compress(codec, data, allocator);}OutOfMemory
Section titled “OutOfMemory”Memory allocation failed.
Common causes:
- System out of memory
- Decompressed size too large for available memory
- Allocator limits reached
Example:
const result = cz.decompress(.zstd, data, allocator) catch |err| { if (err == error.OutOfMemory) { std.debug.print("Insufficient memory for decompression\n", .{}); // Try streaming API or smaller chunks return error.ResourceExhausted; } return err;};Solutions:
- Use streaming API for large data
- Process in smaller chunks
- Set
max_output_sizeto limit memory use - Free other memory before retry
DictionaryMismatch
Section titled “DictionaryMismatch”Dictionary used for decompression doesn’t match compression dictionary.
Common causes:
- Wrong dictionary provided
- Dictionary version mismatch
- Dictionary corrupted
Example:
const result = cz.decompressWithOptions(.zstd, data, allocator, .{ .dictionary = wrong_dictionary,}) catch |err| { if (err == error.DictionaryMismatch) { std.debug.print("Dictionary doesn't match compressed data\n", .{}); return error.ConfigurationError; } return err;};Solutions:
- Verify correct dictionary is used
- Version dictionaries and store version with data
- Include dictionary ID in metadata
InvalidParameter
Section titled “InvalidParameter”Invalid parameter value provided.
Common causes:
expected_sizenot provided forlz4_raw- Invalid option combination
Example:
// lz4_raw requires expected_sizeconst result = cz.decompress(.lz4_raw, data, allocator) catch |err| { if (err == error.InvalidParameter or err == error.InvalidData) { std.debug.print("lz4_raw requires expected_size option\n", .{}); return cz.decompressWithOptions(.lz4_raw, data, allocator, .{ .expected_size = known_size, }); } return err;};Comprehensive Error Handling
Section titled “Comprehensive Error Handling”Pattern for handling all errors:
const cz = @import("compressionz");
pub fn safeDecompress( codec: cz.Codec, data: []const u8, allocator: std.mem.Allocator, max_size: usize,) ![]u8 { return cz.decompressWithOptions(codec, data, allocator, .{ .max_output_size = max_size, }) catch |err| switch (err) { error.InvalidData => { log.err("Invalid or corrupted compressed data", .{}); return error.DataCorruption; }, error.ChecksumMismatch => { log.err("Checksum verification failed", .{}); return error.DataCorruption; }, error.OutputTooLarge => { log.warn("Decompressed size exceeds {d} byte limit", .{max_size}); return error.DataTooLarge; }, error.UnexpectedEof => { log.err("Compressed data truncated", .{}); return error.IncompleteData; }, error.OutOfMemory => { log.err("Out of memory during decompression", .{}); return error.OutOfMemory; }, error.UnsupportedFeature => { log.err("Codec doesn't support requested feature", .{}); return error.UnsupportedOperation; }, else => { log.err("Unexpected decompression error: {}", .{err}); return err; }, };}Error Recovery Strategies
Section titled “Error Recovery Strategies”| Error | Recovery Strategy |
|---|---|
InvalidData | Try auto-detection, re-fetch data |
ChecksumMismatch | Re-fetch from source, restore from backup |
OutputTooSmall | Use larger buffer or allocating API |
OutputTooLarge | Increase limit or reject |
UnexpectedEof | Re-fetch complete data |
UnsupportedFeature | Use different API or codec |
OutOfMemory | Stream process, reduce limits |
DictionaryMismatch | Use correct dictionary |
InvalidParameter | Fix parameters |