Inspired by miette and rustc for Rust and Zig’s own compiler diagnostics, fehler gives you:
- Colorful, source-annotated diagnostics
- File/line/column tracking
- Help messages and fluent API
- Built-in severity levels and labels
- Clean allocator-safe design
Example:

Works great for compilers, preprocessors, and any tool that needs human-readable diagnostics.
GitHub: github.com/ciathefed/fehler
Feedback, bug reports, and suggestions welcome. I’d love to hear what you think or what’s missing.
14 Likes
If this try fails:
then we end up removing existing source form the sources map without replacement.
If this try fails:
we end up additionally leaking owned_content.
You want to Reserve First.
6 Likes
from what i’ve gathered from Reserve First, i think i’ve came up with a solution. before i push the change, some feedback would be appreciated.
pub fn addSource(self: *ErrorReporter, filename: []const u8, content: []const u8) !void {
try self.sources.ensureTotalCapacity(self.sources.count() + 1);
const owned_content = try self.allocator.dupe(u8, content);
errdefer comptime unreachable;
const gop = self.sources.getOrPutAssumeCapacity(filename);
if (gop.found_existing) {
self.allocator.free(gop.value_ptr.*);
}
gop.value_ptr.* = owned_content;
}
4 Likes
Yup, this is perfect! I also like using gop to avoid redundant hashmap lookup!
2 Likes
Ah, wait, I think there’s also .ensureExtraCapcity(1), which might be a bit more convenient here!
2 Likes
It’s called ensureUnusedCapacity.
2 Likes
tsdtas
7
Just wanted to say, that article has significantly changed how I approach error handling in Zig for the better. Thank you for writing it.
1 Like
matklad
8
Thank andrewrk, I just wrote down his Zulip comment
:
yep that reserve capacity should go above the other try
or an errdefer needs to undo the hash map addition. but I usually prefer the reserve pattern
This was new to me as well!
1 Like