# Macos system call validation failure

**URL:** <https://ziggit.dev/t/macos-system-call-validation-failure/16409>\
**Category:** Help\
**Tags:** standard-library\
**Created:** [June 29, 2026, 2:12pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409 "2026-06-29T14:12:50Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anthon](https://ziggit.dev/user_avatar/ziggit.dev/anthon/32/8967_2.png) [@Anthon](https://ziggit.dev/u/Anthon)\
**Post date:** [June 29, 2026, 2:12pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/1 "2026-06-29T14:12:50Z")

</div>

Testing commandline completion with `zigclc` on my macos M1 macbook, I ran into a run-time error:

```zig
[1] 70728 invalid system call CLIGEN_W="zig build --watch -finc" CLIGEN_N="3" _ZIGCLC_CLIGEN_C=czsh zigclc

```

( the env var settings are normally used by the registered function for `zig` commandline completion, here I set the by hand).

Not a very helpful message, and in addition the code worked my server (Intel/Linux). Adding some debug print statements would no longer trigger this invalid system call, but removing those would trigger the run-time error again. This made it useless to bisect down onto the source code area triggering the error.

I hadn’t used a debugger for, literally, multiple decades, but searching told me to use `lldb`:

```zig
zig/zigclc » lldb /Users/anthon/src/zig/zigclc/zig-out/bin/zigclc
(lldb) target create "/Users/anthon/src/zig/zigclc/zig-out/bin/zigclc"
Current executable set to '/Users/anthon/src/zig/zigclc/zig-out/bin/zigclc' (arm64).
(lldb) run
Process 69385 launched: '/Users/anthon/src/zig/zigclc/zig-out/bin/zigclc' (arm64)
>>>>>>>>>> args 0 /Users/anthon/src/zig/zigclc/zig-out/bin/zigclc
>>>>>>>>>> completing 1
Process 69385 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_SYSCALL (code=1697345648)
    frame #0: 0x00000001003dfc94 zigclc`os.linux.aarch64.syscall2(number=getcwd, arg1=6171526312, arg2=1024) at aarch64.zig:32:5
   29 arg1: syscall_arg_t,
   30 arg2: syscall_arg_t,
   31 ) u64 {
-> 32 return asm volatile ("svc #0"
   33 : [ret] "={x0}" (-> u64),
   34 : [number] "{x8}" (@intFromEnum(number)),
   35 [arg1] "{x0}" (arg1),
Target 0: (zigclc) stopped.

```

That is already more useful, but I use getcwd in more than one position in the source, so I used `bt` ( and cut down the repetitive `buf` content):

```zig
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_SYSCALL (code=1697345648)
  * frame #0: 0x00000001003dfc94 zigclc`os.linux.aarch64.syscall2(number=getcwd, arg1=6171526312, arg2=1024) at aarch64.zig:32:5
    frame #1: 0x00000001003dfb10 zigclc`os.linux.getcwd(buf="\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa SNIP xaa"..., size=1024) at linux.zig:1028:20
    frame #2: 0x00000001003df898 zigclc`BuildZig.cwdDepth at BuildZig.zig:471:28
    frame #3: 0x00000001003dbecc zigclc`BuildZig.find_bldzig_dir(io=Io @ 0x000000016fda3d50) at BuildZig.zig:480:27
    frame #4: 0x00000001003d49f4 zigclc`BuildZig.init(alloc=mem.Allocator @ 0x000000016fda3d40, io=Io @ 0x000000016fda3d50, releases=<unavailable>) at BuildZig.zig:47:24
    frame #5: 0x00000001004f9fb8 zigclc`cli.BuildCmdParser.parse(self=0x000000016fde63b0, gpa=mem.Allocator @ 0x000000016fdf3818, out=0x000000016fdf3960, fs=0x000000016fdf3890, args=[]const []const u8 @ 0x000000016fda3990, arg_idx=(ptr = "\U00000002", len = 2), optnl_partial=(ptr = "-finc", len = 5)) at cli.zig:5652:61
    frame #6: 0x00000001003faa18 zigclc`cli.CombinedParsers.parse(self=0x000000016fde63b0, gpa=mem.Allocator @ 0x000000016fdf3818, out=0x000000016fdf3960, fs=0x000000016fdf3890, args=[]const []const u8 @ 0x000000016fdac710, arg_idx=(ptr = "\U00000002", len = 2), optnl_partial=(ptr = "-finc", len = 5)) at cli.zig:67204:56
    frame #7: 0x00000001003f97f0 zigclc`cli.check_completion(alloc=mem.Allocator @ 0x000000016fdf3818, out=0x000000016fdf3960, env=<unavailable>, fs=0x000000016fdf3890, progname=(ptr = "zigclc", len = 6), config=0x000000016fdf5c60) at cli.zig:67374:30
    frame #8: 0x00000001003fa5c4 zigclc`cli.cligen_parser(gpa=mem.Allocator @ 0x000000016fdf3818, out=0x000000016fdf3960, env=cli.Env @ 0x000000016fdf3860, fs=0x000000016fdf3890, sys_args=[]const [:0]const u8 @ 0x000000016fdebdc8, progname=(ptr = "zigclc", len = 6), config=0x000000016fdf5c60) at cli.zig:67393:21
    frame #9: 0x0000000100103bc4 zigclc`cli.command_line_parser(init=<unavailable>, params=cli.ParserOptions @ 0x000000016fdfbce0) at cli.zig:67447:25
    frame #10: 0x000000010011e844 zigclc`main.main(init=process.Init @ 0x000000016fdfe240) at main.zig:32:43
    frame #11: 0x000000010011f1f0 zigclc`start.callMain at start.zig:790:30
    frame #12: 0x000000010011f0e4 zigclc`start.callMainWithArgs at start.zig:692:20
    frame #13: 0x000000010011efa4 zigclc`start.main(c_argc=1, c_argv=0x000000016fdff1f0, c_envp=0x000000016fdff200) at start.zig:717:28
    frame #14: 0x000000019a96eb98 dyld`start + 6076

```

My program is calling `std.os.linux.getcwd()` which has worked for some time without problems, and, as indicated above, works if I put some debug print statements in. Using `up` and `fr v` and checked that the buffer address and length are correct.

The error 1697345648 is a _system call validation failure_, why doesn’t this get thrown now and always? How can I prevent that from happening (apart from adding debug print statements)?

(FWIW the current directory is only 29 characters, so that should fit without problem (and hopefully a better error message), if it had not).

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [June 29, 2026, 6:53pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/2 "2026-06-29T18:53:20Z")

</div>

Are there more source code details?

If the source code is the current zigclc master, then I think the `getcwd` you’re calling is `std.c.getcwd` [here](https://codeberg.org/anthon/zigclc/src/commit/87b01070c3c51aa346ff9e7c788163d033119cd9/src/cli.zig#L116).  
It confuses me that it doesn’t use libc but instead runs the code in `std.os.linux`.

---

<div class="post-metadata">

**Author:** ![Anthon](https://ziggit.dev/user_avatar/ziggit.dev/anthon/32/8967_2.png) [@Anthon](https://ziggit.dev/u/Anthon)\
**Post date:** [June 29, 2026, 9:34pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/3 "2026-06-29T21:34:00Z")

</div>

No it is not the zigclc master, this code is not commited yet.

```zig
    const maxnr: usize = 1024;
    var buf: [maxnr]u8 = undefined;
    _ = std.os.linux.getcwd(&buf, maxnr);

```

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [June 29, 2026, 9:46pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/4 "2026-06-29T21:46:28Z")

</div>

The code under `std.os` isn’t portable, so obviously `std.os.linux` code won’t work on macOS.  
edit: This might be what you want

> [@Get CWD path without \`realPath\`](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/2):
>
> Hi, and welcome to Ziggit slight_smile I know of [std.process.currentPath()](https://ziglang.org/documentation/master/std/#std.process.currentPath). It returns current working directory of the executed program.

---

<div class="post-metadata">

**Author:** ![Anthon](https://ziggit.dev/user_avatar/ziggit.dev/anthon/32/8967_2.png) [@Anthon](https://ziggit.dev/u/Anthon)\
**Post date:** [June 29, 2026, 10:27pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/5 "2026-06-29T22:27:42Z")

</div>

> [@npc1054657282](#):
>
> obviously `std.os.linux` code won’t work on macOS.

Obvious? That does not explain that this worked for weeks and adding a debug print would not make std.os.linux compatible with macOS.

Thanks for the link, I might try that, if nobody can provide an explanation.

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [June 29, 2026, 10:58pm UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/6 "2026-06-29T22:58:55Z")

</div>

> [@Anthon](#):
>
> adding a debug print

Where would adding it make a difference? Is there any related source code?

Is the full source code of `cwdDepth` the one given above? Does its usage depend on some kind of race control flow?

Imagine some possibilities, like `cwdDepth` being a fallback for other solutions, which in most cases won’t even be called. Whether it’s called depends on some cross-thread caching situation; if there’s a cache, it won’t be called. At the same time, the race condition memory access here wasn’t implemented correctly, causing access to the cache to be optimized away, which then fell back to the control flow that needed to call `cwdDepth`, eventually triggering the issue. But after adding debug print statements, those optimizations no longer happen, the cache gets accessed, and calling `cwdDepth` is no longer necessary.

The above are some unrealistic speculations. If possible, I hope the current version of the source code can be uploaded as a branch so that the specific issues can be identified.

---

<div class="post-metadata">

**Author:** ![miagi](https://ziggit.dev/user_avatar/ziggit.dev/miagi/32/6745_2.png) [@miagi](https://ziggit.dev/u/miagi)\
**Post date:** [June 30, 2026, 7:16am UTC](https://ziggit.dev/t/macos-system-call-validation-failure/16409/7 "2026-06-30T07:16:25Z")

</div>

There are two options for this, one would be to open a `.` directory and get a path name from it, other one is `std.process.currentPath()` listed above. But I’d also suggest to use higher level functions than using `os` ones.  
Functions I was referring:  
[std.Io.Dir.realPath()](https://ziglang.org/documentation/master/std/#std.Io.Dir.realPath)  
[std.Io.Dir.OpenDir()](https://ziglang.org/documentation/master/std/#std.Io.Dir.openDir)
