NewsWorld
PredictionsDigestsScorecardTimelinesArticles
NewsWorld
HomePredictionsDigestsScorecardTimelinesArticlesWorldTechnologyPoliticsBusiness
AI-powered predictive news aggregation© 2026 NewsWorld. All rights reserved.
Trending
TrumpTariffTradeFebruaryStrikesAnnounceLaunchNewsPricesMajorMilitaryHongKongCourtDigestSundayTimelineChinaTechSafetyGlobalMarketTestStocks
TrumpTariffTradeFebruaryStrikesAnnounceLaunchNewsPricesMajorMilitaryHongKongCourtDigestSundayTimelineChinaTechSafetyGlobalMarketTestStocks
All Articles
Hacker News
Published 7 days ago

Error payloads in Zig

Hacker News · Feb 15, 2026 · Collected from RSS

Summary

Article URL: https://srcreigh.ca/posts/error-payloads-in-zig/ Comments URL: https://news.ycombinator.com/item?id=47028705 Points: 5 # Comments: 0

Full Article

Feb 13, 2026 I do error payloads in Zig by making a union(enum)-based Diagnostics type for each function. These types have special methods which remove code bloat at call sites. A Diagnostics type can be defined inline, and the errorset can be generated inline from the Diagnostic’s enum tag. pub fn scan( db: *c.sqlite, diag: *diagnostics.FromUnion(union(enum) { SqliteError: sqlite.ErrorPayload, OutOfMemory: void, LoadPluginsError: diagnostics.OfFunction(transforms.loadPlugins).ErrorPayload(error.LoadPluginsError), }), ): diagnostics.Error(@TypeOf(diag))!void { // ... } My diagnostics module as a gist The generated type is a wrapper around an optional payload. It generates an error set type from the union(enum) fields. // diagnostics.zig pub fn FromUnion(comptime _Payload: type) type { return struct { pub const Payload = _Payload; pub const Error = ErrorSetFromEnum(std.meta.FieldEnum(Payload)); payload: ?Payload = null, // ... methods ... }; } The first thing you will want to do is set a payload while you return an error. For this, there is the withContext method. pub fn countRows( alloc: std.mem.Allocator, db: *c.sqlite, opts: Options, diag: *diagnostics.FromUnion(union(enum) { SqliteError: sqlite.ErrorPayload, OutOfMemory: void, }), ) !usize { const st = sqlite.prepareStmt( alloc, db, "SELECT COUNT(*) FROM {0s} WHERE ({1s})", .{ opts.table_name, opts.where_expr }, ) catch |err| return switch (err) { error.SqliteError => diag.withContext(error.SqliteError, .init(db)), error.OutOfMemory => error.OutOfMemory, }; // ... } Here, sqlite.ErrorPayload.init saves 500 bytes of error message from sqlite. That payload gets saved to diag and the error is returned. You would expect callsites to need tons of boilerplate, but it’s actually very common to just need to value copy a payload from one diag to another, and this can be done in a single line of code. pub const BuildDiagnostics = diagnostics.FromUnion(union(enum) { SqliteError: sqlite.ErrorPayload, OutOfMemory: void, // ... 15 more ... }); pub fn build(..., diag: *BuildDiagnostics) !void { // Choose N chunks const n_rows = try diag.call(countRows, .{ alloc, db, opts }); const n_chunks = @max(1, n_rows / opts.chunk_size); } The countRows func needs 4 arguments, but the tuple only has 3. The call method inspects the type of countRows to determine the type of its diag arg, instantiates the diag, calls countRows, and if there is an error, copies the error payload to the *BuildDiagnostics. Written explicitly, this call would be around 5 lines of code. pub fn build(..., diag: *BuildDiagnostics) !void { // Choose N chunks var count_rows_diag: diagnostics.OfFunction(countRows) = .{}; const n_rows = countRows(alloc, db, opts, &count_rows_diag) catch |err| return switch (err) { error.SqliteError => diag.withContext(error.SqliteError, count_rows_diag.get(error.SqliteError)), error.OutOfMemory => error.OutOfMemory, } const n_chunks = @max(1, n_rows / opts.chunk_size); } At the edges, the error payload is accessible for logging or other purposes. fn logBuildError(diag: build.BuildDiagnostics, err: build.BuildDiagnostics.Error) void { switch (err) { error.LoadPluginError => if (diag.get(error.LoadPluginError)) |info| { std.log.err("failed to load plugin '{s}': {s}", .{ info.name, @errorName(info.err) }); } else { std.log.err("failed to load plugin: unknown error", .{}); }, // ... (handle many other errors) ... } } ZLS can’t infer the result of the diag.call invocations, so it can be useful to put in an explicit type annotations. My diagnostics module as a gist


Share this story

Read Original at Hacker News

Related Articles

Hacker Newsabout 6 hours ago
Back to FreeBSD: Part 1

Article URL: https://hypha.pub/back-to-freebsd-part-1 Comments URL: https://news.ycombinator.com/item?id=47108989 Points: 4 # Comments: 0

Hacker Newsabout 6 hours ago
What's the best way to learn a new language?

Article URL: https://www.bbc.com/future/article/20260220-whats-the-best-way-to-learn-a-new-language Comments URL: https://news.ycombinator.com/item?id=47108977 Points: 10 # Comments: 5

Hacker Newsabout 7 hours ago
U.S. Cannot Legally Impose Tariffs Using Section 122 of the Trade Act of 1974

Article URL: https://ielp.worldtradelaw.net/2026/01/guest-post-president-trump-cannot-legally-impose-tariffs-using-section-122-of-the-trade-act-of-1974/ Comments URL: https://news.ycombinator.com/item?id=47108538 Points: 48 # Comments: 12

Hacker Newsabout 8 hours ago
Iranian Students Protest as Anger Grows

Article URL: https://www.wsj.com/world/middle-east/iranian-students-protest-as-anger-grows-89a6a44e Comments URL: https://news.ycombinator.com/item?id=47108256 Points: 17 # Comments: 1

Hacker Newsabout 9 hours ago
Japanese Woodblock Print Search

Article URL: https://ukiyo-e.org/ Comments URL: https://news.ycombinator.com/item?id=47107781 Points: 14 # Comments: 3

Hacker Newsabout 10 hours ago
Palantir's secret weapon isn't AI – it's Ontology. An open-source deep dive

Article URL: https://github.com/Leading-AI-IO/palantir-ontology-strategy Comments URL: https://news.ycombinator.com/item?id=47107512 Points: 37 # Comments: 21