# Newbie: idiom to add information to error

**URL:** <https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214>\
**Category:** Help\
**Tags:** language\
**Created:** [May 22, 2025, 4:23pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214 "2025-05-22T16:23:57Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![hmf](https://ziggit.dev/letter_avatar_proxy/v4/letter/h/91b2a8/32.png) [@hmf](https://ziggit.dev/u/hmf)\
**Post date:** [May 22, 2025, 4:23pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/1 "2025-05-22T16:23:57Z")

</div>

I come from a Java/Scala/Python background and am used to providing additional error information via an exception object that is raised/thrown. I did a search and found the following link:

> **[Advanced Guide to Return Values and Error Unions in Zig](https://gencmurat.com/en/posts/advanced-guide-to-return-values-and-error-unions-in-zig/)**
>
> 1. Basics of Return Values and Error Unions Before diving into advanced topics, let’s cover the fundamentals of return values and error unions in Zig. Und

In section 9.2 Error Context we have:

```zig
 const ErrorContext = struct {
    err: anyerror,
    context: []const u8,

    fn create(err: anyerror, context: []const u8) ErrorContext {
        return .{ .err = err, .context = context };
    }
};

fn riskyOperation() ErrorContext!void {
    return ErrorContext.create(error.SomethingWentWrong, "Failed during critical step");
}

fn main() !void {
    riskyOperation() catch |err| {
        std.debug.print("Error: {} (Context: {})\n", .{ err.err, err.context });
        return;
    };
}

```

I am using Zig 15-dev and if fails to compile. I am assuming there have been changes that don’t allow this. What is the idiomatic way to do this? I was thinking of using a pointer to a parameter, but this means dragging this through all the functions. I would also like to avoid the use of global variables.

TIA

---

<div class="post-metadata">

**Author:** ![Eisenhauer](https://ziggit.dev/letter_avatar_proxy/v4/letter/e/76d3ee/32.png) [@Eisenhauer](https://ziggit.dev/u/Eisenhauer)\
**Post date:** [May 22, 2025, 4:44pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/2 "2025-05-22T16:44:05Z")

</div>

I suspect the article you read contains LLM hallucinations. There are several other code samples in there which I believe are also not compiling.

---

<div class="post-metadata">

**Author:** ![Justus2308](https://ziggit.dev/user_avatar/ziggit.dev/justus2308/32/5305_2.png) [@Justus2308](https://ziggit.dev/u/Justus2308)\
**Post date:** [May 22, 2025, 4:48pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/3 "2025-05-22T16:48:05Z")

</div>

I suppose you could do something like this:

```zig
fn ErrorUnionWithContext(comptime T: type) type {
    return union(enum) {
        ok: T,
        error_with_context: struct {
            err: anyerror,
            context: []const u8,
        },

        pub fn success(value: T) @This() {
            return .{ .ok = value };
        }

        pub fn failure(err: anyerror, context: []const u8) @This() {
            return .{ .error_with_context = .{
                .err = err,
                .context = context,
            } };
        }

        pub fn unwrap(self: @This()) !T {
            return switch (self) {
                .ok => |value| value,
                .error_with_context => |e| e.err,
            };
        }
    };
}

```

and use this as the sole return value of your functions as a makeshift error union.  
But make sure that `context` doesn’t go out of scope as soon as your function returns (you could make it `comptime`).

---

<div class="post-metadata">

**Author:** ![pachde](https://ziggit.dev/user_avatar/ziggit.dev/pachde/32/2485_2.png) [@pachde](https://ziggit.dev/u/pachde)\
**Post date:** [May 22, 2025, 4:53pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/4 "2025-05-22T16:53:43Z")

</div>

Only Zig errors can occur to the left of the !. They cannot be a struct with a payload. One way to do this is return the error code as zig usual and have an out-parameter for the error payload. This can receive a pointer for something dynamically allocated by your function, in which case the caller is responsible for deallocating it, or the caller can pass the address of an error payload struct that is filled by your function – which can live where you choose – could be a global or some other app-wide context, or a local in just the caller. Or, you can use the single result value tagged union approach.

I am guessing that it’s likely best to separate ok result from error result so that your main result data flow isn’t carrying around error information.

---

<div class="post-metadata">

**Author:** ![00JCIV00](https://ziggit.dev/user_avatar/ziggit.dev/00jciv00/32/1069_2.png) [@00JCIV00](https://ziggit.dev/u/00JCIV00)\
**Post date:** [May 22, 2025, 6:45pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/5 "2025-05-22T18:45:27Z")

</div>

This is commonly referred to as the “Diagnostics” pattern. There are several examples in Zig’s stdlib. Here’s one for `std.json`: [std.json.Diagnostics](https://ziglang.org/documentation/master/std/#std.json.Diagnostics).

---

<div class="post-metadata">

**Author:** ![hmf](https://ziggit.dev/letter_avatar_proxy/v4/letter/h/91b2a8/32.png) [@hmf](https://ziggit.dev/u/hmf)\
**Post date:** [May 22, 2025, 7:27pm UTC](https://ziggit.dev/t/newbie-idiom-to-add-information-to-error/10214/6 "2025-05-22T19:27:28Z")

</div>

@pachde and @00JCIV00  
So the “diagnostics pattern” uses a local variable solution, which has the advantage of not requiring memory allocation and free. Seems doable. May be the simplest option for me.

@Justus2308 I have been looking at this carefully, and it looks like an interesting but more complex alternative to the “diagnostics pattern”. The use of comptime to avoid loss of scope is interesting.

Thanks for the replies.
