Unable to make HTTPS calls from build.zig?

Hello everyone, happy December!

I was looking at my advent of code framework the other day and started refactoring some things. One idea involved fetching the puzzle input directly via zig using the build system. Something like:

  1. In build.zig: check if input file (e.g. day01.txt) exists, otherwise fetch it from adventofcode.com
  2. Provide the result via @embedFile

After implementing this idea I faced an error during the build phase:

/Users/gs/.zvm/0.15.1/lib/std/http/Client.zig:1683:26: 0x102ecb28b in request (build)
        if (disable_tls) unreachable; // <--- What's going on here?
                         ^
/Users/gs/.zvm/0.15.1/lib/std/http/Client.zig:1789:26: 0x102ea8ae3 in fetch (build)
    var req = try request(client, method, uri, .{
                         ^
/Users/gs/git/zig/advent-of-code/modules/aoc/src/input.zig:53:25: 0x102ea808f in getPuzzleInputFromServer (build)
    _ = try client.fetch(.{
                        ^
/Users/gs/git/zig/advent-of-code/modules/aoc/build.zig:35:43: 0x102ea99ab in fetchInputData__anon_24393 (build)
    _ = try input.getPuzzleInputFromServer(b.allocator, year, day, puzzle_input_path);
                                          ^
/Users/gs/git/zig/advent-of-code/2025/build.zig:20:27: 0x102eaa627 in build (build)
    try aoc.fetchInputData(b, cwd, YEAR, DAY);
                          ^
/Users/gs/.zvm/0.15.1/lib/std/Build.zig:2215:44: 0x102e96a8f in runBuild__anon_21112 (build)
        .error_union => try build_zig.build(b),
                                           ^
/Users/gs/.zvm/0.15.1/lib/compiler/build_runner.zig:366:29: 0x102e8ebff in main (build)
        try builder.runBuild(root);
                            ^
/Users/gs/.zvm/0.15.1/lib/std/start.zig:627:37: 0x102e98cd7 in main (build)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x19a7e6b97 in ??? (???)
???:?:?: 0x0 in ??? (???)
error: the following build command crashed:
.zig-cache/o/d72d5999601d123a28ad4c6209e17a08/build /Users/gs/.zvm/0.15.1/zig /Users/gs/.zvm/0.15.1/lib /Users/gs/git/zig/advent-of-code/2025 .zig-cache /Users/gs/.cache/zig --seed 0xfe568de -Z2a380e55f54b226b run -- 1

The build fails because std.http.Client.disable_tls is set to false for some reason.

The HTTPS call clearly works from a really simple compiled zig code example. So I started digging into the source and found that lib/compiler/build_runner.zig is setting std_options.http_disable_tls to true:

pub const std_options: std.Options = .{
    .side_channels_mitigations = .none,
    .http_disable_tls = true, // <--
    .crypto_fork_safety = false,
};

from my understanding it’s not possible to overwrite these std_options in the build runner, or is it somehow?

For now I just patched the build_runner.zig source code on my zig install - which works fine. But I wonder if there’s specific reasons why the build system would disable TLS and if these std_options in the build_runner should eventually be configurable?

Instead of running this code in build.zig, create a run step for a program that fetches the payload instead, something like:

const cmd = b.addRunArtifact(zig_exe_that_fetches_stuff);
cmd.addArg(“whatever input you might want”);
const payload = cmd.captureStdOut(); // use this as anonymous import

https://github.com/ziglang/zig/blob/master/lib/std/Build/Step/Run.zig (is a good resource)

Doing IO in build.zig directly is not generally good idea as it runs every time, and it might even break in future if builds become sandboxed.

7 Likes

I know there was a talk about running build tasks in a sandbox but what is the purpose of the sandbox if you can just run exe?

1 Like

The build runner can still sandbox executables, so they can only access certain directories, restrict syscalls and so on. It’s even possible to do this on operating systems that don’t support such things by compiling to wasm. Of course, sometimes not being sandboxed is useful, so I believe there would be a option for escape hatch.

https://github.com/ziglang/zig/issues/14286

1 Like

One reason is precisely to prevent you from doing these operations in build.zig, using a seperate executable makes it much easier to take advantage of the build systems caching.

Also executables run by the build system could still be sandboxed.

1 Like

Thought about that, too. But essentially that’d mean a dependency to a compiled binary at hand (whatever that is, a zig exe or curl/wget or whatever). I kind of liked the idea that the build system can fetch input data it needs without additional third party dependencies or compiling binaries upfront.

On the other hand it sounds a bit dangerous if a build system allows to fetch arbitrary things from the web, so the argument for a sandbox makes total sense :thinking:.

Even without sandboxing, if you do these directly in build.zig which is meant for constructing a build graph, you are making network request every time you run the build. Using run steps, lets the runner to cache the runs, and only rerun them if needed.

3 Likes

No just a dependency to source code that defines how to compile and build that tool, basically a normal executable compile step, that step is then automatically compiled before it is used to fetch the needed stuff.

2 Likes