Skip to main content
This page covers errors you’re likely to hit and how to resolve them.

Shared memory errors

zinc_create fails with AlreadyExists (-17)

A region with that name already exists in /dev/shm/. Either:
  1. An earlier process crashed without cleaning up.
  2. Another process is actively using the region.
Fix on Linux:
Fix on macOS: The shared memory object is kernel-managed and can’t be removed from the filesystem. Restart your processes, or use a unique name per run (append a PID or timestamp).

zinc_create fails with InvalidSize (-22)

Capacity must be a positive multiple of the system page size (typically 4096 bytes). The error includes the required page size.

zinc_open fails with NotFound (-2)

No region with that name exists. The creating process may have already closed and unlinked it, or it hasn’t been created yet. Ensure the creator is running and using the same name. Region names are case-sensitive.

PermissionDenied (-1)

On Linux, shared memory objects are created with mode 0600 (owner read/write). If another user created the region, your process can’t open it. All processes sharing a region must run as the same user.

Library not found errors

Python: OSError: cannot load library

Fix: Build the core library first and set the library path:

Node: npm run build fails

The Node adapter uses napi-rs. If npm run build fails with missing symbols:
The build links against the Cargo workspace in ../../core, so you need the full repo checked out.

Go: cgo linker errors

Fix: Point the linker at the built core library:

Java: UnsatisfiedLinkError

JNA looks for libzinc_core.so on java.library.path. Set it:

C#: DllNotFoundException

Copy libzinc_core.so / libzinc_core.dylib to the working directory or set LD_LIBRARY_PATH / DYLD_LIBRARY_PATH before running .NET tests.

Bun: dlopen fails

Bun’s bun:ffi looks for the library at a path relative to the source file. By default it expects:
Build the core first:

Deno: --allow-ffi required

Deno’s FFI requires the --allow-ffi permission:

macOS-specific issues

Wait burns CPU

On macOS, wait() uses an adaptive spin loop because futex doesn’t exist. A waiting thread will consume CPU for the duration of the wait. This is by design. Mitigations:
  • Keep timeouts short (< 100ms).
  • Use notify() + manual polling for very long waits.
  • Consider using a dispatch_semaphore in shared memory on top of a Zinc region if you need efficient sleeping waits on macOS.

Region names not visible in filesystem

Unlike Linux, macOS shared memory objects don’t appear as files. ls /dev/shm/ won’t work. Use a coordination mechanism (file lock, socket, env var) to tell processes which names to use.

shm_open fails with ENOMEM

macOS has a very low default limit for shared memory. Check:
If too low, increase it:

Linux-specific issues

/dev/shm permissions

Some container runtimes mount /dev/shm with restricted permissions:
If you see PermissionDenied, ensure the mount has the sticky bit (t) set and is world-writable. In Docker, add:

Too many regions (ENFILE / EMFILE)

Each open region holds a file descriptor. The default per-process limit is typically 1024. Raise it:

vm.max_map_count exhaustion

Each mmap call creates a mapping entry in the kernel’s VMA tree. If you open many regions, you may hit the limit:
Typical default is 65530, which should be enough for most use cases.

General debugging

Enable verbose errors

The core library returns error codes as negative errno values. Most adapter wrappers try to map these to readable messages. If you get a cryptic numeric error, look it up:

Check for zombie regions

Regions persist in /dev/shm/ if the creator crashes without unlinking. To find them:
The filename includes the region name. If no process is using a region (check with fuser or lsof), you can safely remove the file.

Verify the core library is compatible

Keep the header (include/zinc.h) and the library in sync, they’re built together.

File descriptor usage

Each zinc_create or zinc_open holds one file descriptor from shm_open and one anonymous descriptor from mmap. Both are released on zinc_close. If your process opens many regions, mind the per-process FD limit.