Tech 6 min read

The 49.7-Day macOS Bug That Silently Kills All New TCP Connections

IkesanContents

Photon published an article on April 9, 2026, revealing a critical bug in macOS’s TCP networking stack.
After 49 days, 17 hours, 2 minutes, and 47 seconds of continuous uptime—roughly 49.7 days—all new TCP connections become impossible to establish.

Existing connections and pings keep working. The machine appears perfectly normal.
But new SSH connections, web requests, and API calls all time out.
The only way to recover is a reboot.

What Is tcp_now?

The XNU kernel in macOS has a variable called tcp_now.
It tracks elapsed milliseconds since system boot, serving as the TCP stack’s internal clock.

The problem is that this variable is declared as a 32-bit unsigned integer (uint32_t).

uint32_t tcp_now;  // 0 to 4,294,967,295

The maximum value it can hold is 4,294,967,295.
In terms of time:

4,294,967,295 ms
= 4,294,967.295 seconds
= 71,582.788 minutes
= 1,193.046 hours
= 49 days 17 hours 2 minutes 47.296 seconds

Once this time elapses, the counter wraps around to zero.
A classic 32-bit integer overflow.

Why TCP Connections Die

tcp_now is used to manage TCP’s TIME_WAIT state.

TIME_WAIT holds a connection slot for a period after a TCP connection is closed.
It prevents delayed packets from a recently closed connection from being confused with a new one.

Under normal operation, slots are freed once the TIME_WAIT expiry passes, making them available for new connections.
But when tcp_now overflows and wraps to zero, the expiry check logic breaks.

// Simplified illustration
if (tcp_now - conn->start_time > TIMEOUT) {
    expire_connection(conn);  // Free the slot
}
// When tcp_now wraps to zero, this condition stops evaluating to true

TIME_WAIT connections are never freed, and ephemeral ports gradually exhaust.

graph TD
    A["49.7 days since boot"] --> B["tcp_now wraps<br/>around to 0"]
    B --> C["TIME_WAIT expiry<br/>check stops working"]
    C --> D["Closed connection<br/>slots never freed"]
    D --> E["Ephemeral port pool<br/>(65,536) gradually exhausts"]
    E --> F["All new TCP<br/>connections fail"]
    F --> G["Existing connections<br/>and ICMP still work"]
    G --> H["Monitoring dashboards<br/>show system as healthy"]

A system has roughly 65,536 ephemeral ports.
A busy server processing thousands of TCP connections per hour will exhaust them within minutes after the overflow.
Even lightly used machines will eventually hit the same wall.

Extremely Difficult to Detect

What makes this bug insidious is that the machine doesn’t look broken.

ItemBehavior
pingResponds normally
Existing SSH sessionsMaintained
Existing DB connectionsMaintained
CPU/Memory usageNormal
System logsNo anomalous entries
New TCP connectionsTime out

ICMP (ping) is processed through a separate path from TCP, so it’s unaffected.
Existing TCP connections don’t need new ports, so they stay alive.
The only thing that dies is the establishment of new TCP connections.

If your monitoring system only performs health checks over existing connections, the dashboard shows “healthy.”
Administrators restart the machine without finding the root cause, only to encounter the same issue 49.7 days later.

RFC 7323 Anticipated This Problem 25 Years Ago

RFC 7323, “TCP Extensions for High Performance,” explicitly defines how to handle TCP timestamp overflows.

It specifies modular arithmetic comparisons to handle counter wraparound—a logic that correctly determines temporal ordering even when the counter wraps to zero.

// RFC 7323-compliant overflow-safe comparison
// Determines whether a is "after" b
static inline bool tcp_time_after(uint32_t a, uint32_t b) {
    return (int32_t)(a - b) > 0;
}
// The signed cast ensures correct comparison even after wraparound

Apple’s XNU kernel does not implement this RFC 7323-compliant logic.
It uses a simple integer comparison (a > b), which breaks the instant tcp_now wraps to zero.

The XNU kernel source code is publicly available on GitHub, meaning this issue was theoretically verifiable.
Yet it went unnoticed for years.

Discovered in Photon’s Mac mini Fleet

Photon operates a fleet of Mac minis, processing thousands of network transactions per hour.

At some point, machines began exhibiting the same puzzling behavior in sequence.
New connections were refused, but all diagnostic metrics looked normal.
Administrators were rebooting machines without understanding the cause.

The breakthrough came when they noticed that all affected machines had the same uptime duration.
They set up a monitoring script on a separate machine and let it approach the same uptime threshold.
At precisely 49.7 days, new connections stopped being established.

Investigation of the XNU kernel source code identified the 32-bit integer overflow in tcp_now as the root cause.

Windows 95/98 Had the Same 49.7-Day Bug

In 1999, Windows 95/98 had the same 49.7-day problem.
A 32-bit system timer overflowed, causing a blue screen crash.

AspectWindows 95/98 (1999)macOS XNU (2026)
Cause32-bit timer overflowtcp_now (uint32_t) overflow
Trigger~49.7 days49 days 17h 2m 47s
SymptomBlue screenSilent new TCP connection failure
DetectabilityImmediately obviousExtremely subtle
RFC complianceN/ARFC 7323 (not implemented)

Windows 95/98 was arguably better in this regard.
A blue screen makes the problem immediately apparent, and you reboot to recover.
On macOS, the machine keeps running while only new network connections silently die.
In low-traffic environments, this could go unnoticed for hours.

Similar cases exist elsewhere.
The Boeing 787 had a reported issue where the power management system shut down after 51 days of continuous operation.
Linux kernel had a scheduler bug that manifested after 208 days.
32-bit integer overflow is a recurring time bomb throughout computing history.

Impact and Workarounds

According to Photon’s report, macOS Catalina (10.15) and later are affected.

However, community reports on Hacker News are mixed.
Some report no issues after 600+ days of uptime, while others observed massive TIME_WAIT accumulation at 55 days.

The discrepancy depends on network traffic volume.
Port pool exhaustion speed is proportional to TCP connection frequency.
Lightly used machines may continue operating for a while after the overflow.
But the tcp_now clock freeze itself occurs reliably—exhaustion is just a matter of time.

Sleep behavior may also be a factor.
Laptops frequently enter sleep mode, making it harder for kernel uptime to reach 49.7 days.
Always-on desktops and servers are at highest risk.

Current Mitigation

The only confirmed workaround is to reboot before reaching 49.7 days.

If you’re running always-on Macs (home servers, build machines, CI environments, media servers, etc.),
scheduling a reboot every 30–45 days is recommended.

A permanent fix requires Apple to update the XNU kernel.
The technical solution is straightforward:

  1. Change tcp_now to a 64-bit counter
  2. Or implement the modular arithmetic approach specified in RFC 7323

The standard specification has existed for years.
As of April 2026, there has been no official comment or patch timeline from Apple.


If you’re using macOS as a server, put a reboot every seven weeks on your calendar.
Who would have thought we’d step on the same landmine from Windows 25 years ago, this time on macOS in 2026.