Context
#281 restored the Intel macOS test lane, which had been red for its entire life (14 runs, 14 failures, zero successes). The restored lane is the first thing in this repository to run the test suite on macOS: rust-native's matrix is [ubuntu-latest, windows-latest], macos-arm-tests is gated off by ENABLE_MACOS_RUNNERS, and the two Apple-hosted matrices in ci.yml run only the compiler-policy and screenshot proofs.
So the first green-ish run (35125870261) ran 973 tests on x86_64-apple-darwin and 23 failed. Diagnosing them split the set in two: environment artifacts of a Recovery guest, and genuine macOS portability findings that would fail on any macOS host and had simply never been exercised.
The artifacts are excluded by name in ci/macos-x64/recovery-guest.sh with the evidence recorded inline and in ci/macos-x64/README.md. This issue is for the ones that are real. They are currently excluded from the lane too — otherwise the lane cannot be green — but excluding them is a deferral, not a resolution, and nothing else in CI will catch them.
Findings
1. cap-primitives 4.0.3 panics on a negative st_rdev on macOS — 12 tests
The largest group, and the only one caused by a dependency rather than by a test.
called `Result::unwrap()` on an `Err` value: TryFromIntError(())
at cap-primitives-4.0.3/src/rustix/fs/metadata_ext.rs:171
Line 171 is:
rdev: u64::try_from(stat.st_rdev).unwrap(),
Two lines above it, the same struct handles the identical problem correctly:
dev: if stat.st_dev < 0 {
i64::try_from(stat.st_dev).unwrap() as u64
} else {
u64::try_from(stat.st_dev).unwrap()
},
That guard exists because dev_t is signed on macOS (i32) and unsigned on Linux. The author knew; rdev just never got the same treatment. On Linux the branch is dead, which is exactly why only a macOS run exposes it. rustix's libc backend declares pub st_rdev: c::dev_t, so the conversion is genuinely fallible.
No fixed release exists — cap-primitives 4.0.3 is the newest 4.x on crates.io (the next entries are 3.4.6, a backport on the older line), so this cannot be resolved by a version bump.
Affected: the 12 wasm::worker::output::tests / wasm::worker::tests cases exercised through the capability-based filesystem.
2. macOS rejects the TLS test fixtures' certificates — 2 tests
reqwest::Error { kind: Request, source: ... Error { code: -67901,
message: "The validity period in the certificate exceeds the maximum allowed." } }
macOS's Security framework enforces a maximum TLS certificate validity (825 days) that the fixtures' self-signed certificates exceed. trusted_local_tls_preserves_body and trusted_https_downgrade_is_rejected_before_plaintext_connection are not #[ignore]d, so they run anywhere the suite runs on macOS.
3. macOS canonicalizes /var to /private/var — 1 test
assertion `left == right` failed
left: "/private/var/folders/zz/.../T/.tmpvPapPF/target"
right: "/var/folders/zz/.../T/.tmpvPapPF/target"
context_metadata_and_link_read_do_not_follow_final_symlinks compares a path it built against a canonicalized one. /var is a symlink to /private/var on macOS, so the two differ. Linux and Windows have no equivalent alias, which is why this is macOS-only.
4. macOS returns ENOTSUP for the readiness marker's rename — 2 tests
Os { code: 45, kind: Uncategorized, message: "Operation not supported" }
failed_marker_write_is_cleaned_up_and_existing_marker_is_preserved and marker_is_invisible_until_payload_is_complete. Both depend on an atomic no-replace rename for the marker's publish step. Linux's renameat2(RENAME_NOREPLACE) has no drop-in macOS equivalent, and the call is returning ENOTSUP rather than falling back.
This one is worth prioritising: it is the same publish-atomicity property that the wasm::worker output path relies on, so a no-op fallback would be a correctness problem rather than a test-only one.
5. APFS rejects invalid-UTF-8 file names with EILSEQ — 1 test
Os { code: 92, kind: Uncategorized, message: "Illegal byte sequence" }
tree_hash::invalid_utf8_file_names_fail_instead_of_colliding creates a file with invalid UTF-8 in its name and asserts the tree hash fails rather than colliding. On Linux arbitrary bytes are legal; on APFS the name cannot be created at all, so the test fails one step earlier than it asserts. The tree_hash property still needs to hold on macOS, it just cannot be provoked this way.
Open question
Findings 2–5 would also fail on aarch64 macOS. We cannot currently tell whether they are Intel-specific, because macos-arm-tests is disabled. Once this lane has a green record it is worth deciding whether to flip ENABLE_MACOS_RUNNERS, which would give a second data point on the same tests.
Not in scope
EXCLUDE_ROOT (the guest runs as root, so a chmod 000 file is still readable), EXCLUDE_TTY (no controlling terminal), and EXCLUDE_VM_TIMING (two cores in a VM) are artifacts of the Recovery environment, not macOS findings, and are excluded for that reason.
🤖 Generated with Claude Code
Context
#281 restored the Intel macOS test lane, which had been red for its entire life (14 runs, 14 failures, zero successes). The restored lane is the first thing in this repository to run the test suite on macOS:
rust-native's matrix is[ubuntu-latest, windows-latest],macos-arm-testsis gated off byENABLE_MACOS_RUNNERS, and the two Apple-hosted matrices inci.ymlrun only the compiler-policy and screenshot proofs.So the first green-ish run (35125870261) ran 973 tests on
x86_64-apple-darwinand 23 failed. Diagnosing them split the set in two: environment artifacts of a Recovery guest, and genuine macOS portability findings that would fail on any macOS host and had simply never been exercised.The artifacts are excluded by name in
ci/macos-x64/recovery-guest.shwith the evidence recorded inline and inci/macos-x64/README.md. This issue is for the ones that are real. They are currently excluded from the lane too — otherwise the lane cannot be green — but excluding them is a deferral, not a resolution, and nothing else in CI will catch them.Findings
1.
cap-primitives4.0.3 panics on a negativest_rdevon macOS — 12 testsThe largest group, and the only one caused by a dependency rather than by a test.
Line 171 is:
Two lines above it, the same struct handles the identical problem correctly:
That guard exists because
dev_tis signed on macOS (i32) and unsigned on Linux. The author knew;rdevjust never got the same treatment. On Linux the branch is dead, which is exactly why only a macOS run exposes it.rustix's libc backend declarespub st_rdev: c::dev_t, so the conversion is genuinely fallible.No fixed release exists —
cap-primitives4.0.3 is the newest 4.x on crates.io (the next entries are3.4.6, a backport on the older line), so this cannot be resolved by a version bump.Affected: the 12
wasm::worker::output::tests/wasm::worker::testscases exercised through the capability-based filesystem.cap-std/cap-primitiveswith the code asymmetry above. — done: cap-primitives 4.0.3 panics with TryFromIntError on a negative macOS st_rdev sunfishcode/cap-std#427.[patch.crates-io], or dropcap-stdfrom the worker-output path.st_rdev, not just these tests — the impact is not test-only.2. macOS rejects the TLS test fixtures' certificates — 2 tests
macOS's Security framework enforces a maximum TLS certificate validity (825 days) that the fixtures' self-signed certificates exceed.
trusted_local_tls_preserves_bodyandtrusted_https_downgrade_is_rejected_before_plaintext_connectionare not#[ignore]d, so they run anywhere the suite runs on macOS.3. macOS canonicalizes
/varto/private/var— 1 testcontext_metadata_and_link_read_do_not_follow_final_symlinkscompares a path it built against a canonicalized one./varis a symlink to/private/varon macOS, so the two differ. Linux and Windows have no equivalent alias, which is why this is macOS-only.4. macOS returns
ENOTSUPfor the readiness marker's rename — 2 testsfailed_marker_write_is_cleaned_up_and_existing_marker_is_preservedandmarker_is_invisible_until_payload_is_complete. Both depend on an atomic no-replace rename for the marker's publish step. Linux'srenameat2(RENAME_NOREPLACE)has no drop-in macOS equivalent, and the call is returningENOTSUPrather than falling back.This one is worth prioritising: it is the same publish-atomicity property that the
wasm::workeroutput path relies on, so a no-op fallback would be a correctness problem rather than a test-only one.ENOTSUPhere or the guest's APFS does. — production: no,persist_noclobberhas no production caller. The real-hardware half stays open as the checkbox in the correction comment below.5. APFS rejects invalid-UTF-8 file names with
EILSEQ— 1 testtree_hash::invalid_utf8_file_names_fail_instead_of_collidingcreates a file with invalid UTF-8 in its name and asserts the tree hash fails rather than colliding. On Linux arbitrary bytes are legal; on APFS the name cannot be created at all, so the test fails one step earlier than it asserts. Thetree_hashproperty still needs to hold on macOS, it just cannot be provoked this way.#[cfg]-gate the on-disk construction. — fixed in fix(macos): make three portability findings correct on macOS #284 (the test accepts the filesystem refusing the name).Open question
Findings 2–5 would also fail on aarch64 macOS. We cannot currently tell whether they are Intel-specific, because
macos-arm-testsis disabled. Once this lane has a green record it is worth deciding whether to flipENABLE_MACOS_RUNNERS, which would give a second data point on the same tests.Not in scope
EXCLUDE_ROOT(the guest runs as root, so achmod 000file is still readable),EXCLUDE_TTY(no controlling terminal), andEXCLUDE_VM_TIMING(two cores in a VM) are artifacts of the Recovery environment, not macOS findings, and are excluded for that reason.🤖 Generated with Claude Code