Software (please complete the following information):
- Operating system: iOS 26.6.1 (Darwin 25.6.0, aarch64)
- NymVPN version: nym-vpn-lib 2026.12.1-beta.3 (iOS beta)
Describe the bug
The NymMixnetTunnel extension crashes on startup with a Rust panic when the log file cannot be created:
panic: initializing rolling file appender failed: InitError { context: "failed to create log file",
source: Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" } }
nym_vpn_lib::logging::FileAppender::new
nym_vpn_lib::logging::setup_logging
_uniffi_nym_vpn_lib_uniffi_fn_func_initlogger
FileAppender::new (nym-vpn-core/crates/nym-vpn-lib/src/logging.rs) uses tracing_appender::rolling::never, which .expect()s on any error while opening the log file, so a logging failure takes down the whole tunnel process.
The EPERM comes from iOS Data Protection. The extension calls initLogger from PacketTunnelProvider.init() with a log dir inside the app-group container. No target sets a default-data-protection entitlement, so files get CompleteUntilFirstUserAuthentication. With the always-on NEOnDemandRuleConnect rule enabled, iOS launches the extension at boot before the device is unlocked, and open() on the protected log file is refused. The directory existed (error context is "failed to create log file", not "... log directory"), only the file open failed.
Sentry: nym-vpnd issue 7462203070.
To Reproduce
Steps to reproduce the behavior:
- In the app, enable on-demand / always-on connection.
- Reboot the iPhone and leave it locked (do not enter the passcode).
- Wait for the on-demand rule to launch the tunnel extension.
- Observe the crash in Sentry / device crash logs. The VPN does not come up until the device is unlocked.
Expected behavior
Logger initialisation must never abort the tunnel. If the log file cannot be opened, the extension should log a warning via oslog, continue without the file layer, and optionally reopen the file lazily on first write once the device is unlocked. The Swift-side LogFileManager in the same process already tolerates this case with try?; the Rust side should match.
Screenshots
N/A. Sentry stack trace above.
Additional context
- Impact: after an overnight iOS update or reboot, auto-connect fails and every on-demand launch attempt is reported to Sentry as a fatal crash until the user unlocks the phone.
- Proposed fix in
nym-vpn-lib:
- Make
FileAppender::new fallible using RollingFileAppender::builder().build(dir) and return the InitError to setup_logging.
- In
setup_logging, skip the file layer with a warning instead of panicking.
- Optional: reuse
FileAppender::refresh to retry opening the file on first write.
- Optional: surface the failure through
initLogger into the existing PacketTunnelProvider.logInitFailure field.
- Alternative or complementary: set
NSFileProtectionNone / completeUntilFirstUserAuthentication explicitly on the Logs directory from Swift, but the Rust side should still not panic.
Software (please complete the following information):
Describe the bug
The NymMixnetTunnel extension crashes on startup with a Rust panic when the log file cannot be created:
FileAppender::new(nym-vpn-core/crates/nym-vpn-lib/src/logging.rs) usestracing_appender::rolling::never, which.expect()s on any error while opening the log file, so a logging failure takes down the whole tunnel process.The
EPERMcomes from iOS Data Protection. The extension callsinitLoggerfromPacketTunnelProvider.init()with a log dir inside the app-group container. No target sets adefault-data-protectionentitlement, so files getCompleteUntilFirstUserAuthentication. With the always-onNEOnDemandRuleConnectrule enabled, iOS launches the extension at boot before the device is unlocked, andopen()on the protected log file is refused. The directory existed (error context is "failed to create log file", not "... log directory"), only the file open failed.Sentry: nym-vpnd issue 7462203070.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Logger initialisation must never abort the tunnel. If the log file cannot be opened, the extension should log a warning via oslog, continue without the file layer, and optionally reopen the file lazily on first write once the device is unlocked. The Swift-side
LogFileManagerin the same process already tolerates this case withtry?; the Rust side should match.Screenshots
N/A. Sentry stack trace above.
Additional context
nym-vpn-lib:FileAppender::newfallible usingRollingFileAppender::builder().build(dir)and return theInitErrortosetup_logging.setup_logging, skip the file layer with a warning instead of panicking.FileAppender::refreshto retry opening the file on first write.initLoggerinto the existingPacketTunnelProvider.logInitFailurefield.NSFileProtectionNone/completeUntilFirstUserAuthenticationexplicitly on the Logs directory from Swift, but the Rust side should still not panic.