Connectivity Troubleshooting · Clash Technical Blog

Mihomo macOS TUN: ENOTSOCK and high CPU

macOS Mixed TUN repeatedly logs ENOTSOCK with high CPU? Check the actual core and the v1.19.32 fix, back up and upgrade, grant permissions again, then verify the error loop and connectivity. Restore the configuration if this fails.

  • macOS
  • Mixed TUN
  • ENOTSOCK
  • Mihomo
  • v1.19.32
On this page

After enabling TUN proxying on a Mac, Mihomo’s CPU usage stays high and errors keep repeating in the logs. Where should you start? Check the Mixed TUN error pattern and the actual core version. Use the logs, CPU usage, and real network access together to judge whether the changes helped.

Which symptoms match the Mixed TUN packet-read error loop?

Check whether socket operation on non-socket keeps repeating in the macOS Mixed TUN logs, and whether Mihomo continues to consume CPU. A single startup error, normal traffic load, or only increased memory usage in the client UI is not enough to identify this packet-read error loop.

Issue #3310 reports a failure involving Clash Party 2.0.3, Mihomo v1.19.31, and the mixed stack on Apple Silicon. No reliable steps to trigger it were established, and any connection to waking from sleep, switching networks, or reloading configuration remains unconfirmed. This does not establish that every Mac or every case of high CPU with TUN has the same problem.

Error text for comparison; this is not a command to run
batch read packet: socket operation on non-socket

How does v1.19.32 stop the repeated packet-read error loop?

Check the Mihomo core, not just the client version. Record the actual version and channel on the Clash Party core card, along with the TUN switch and stack value. Keep independent backups of subscriptions, local profiles, overrides and app settings. Updating the client while it still runs the old core does not load this fix.

v1.19.32 changes how packet-read errors are handled on macOS. It treats ENOTSOCK and EBADF as a closed state, allowing Mixed TUN to stop reading rather than repeatedly logging the same error. This fixes the error loop; the original cause of the connection failure and whether network access has recovered still need separate checks.

What to do for each version and error

What is happeningFirst action
Running v1.19.31, with Mixed TUN repeatedly reporting the same error while reading packetsKeep the evidence and an independent backup, update to v1.19.32 with this fix, then grant permissions again and verify operation.
Already running v1.19.32, but the error persists or returnsTurn off TUN first and save a short log from the new version along with the current settings. The existing fix does not establish that every error with the same name has been resolved.
No matching error while reading packets; only memory growth in the client UI, download issues, or ordinary connectivity problemsTroubleshoot the actual memory, download, or connectivity problem. Do not switch the protocol stack or reset the configuration just because CPU usage is high.
Dependency versions and source evidence
Mihomo v1.19.31 uses sing-tun v0.4.24, while the go.mod for v1.19.32 uses v0.4.27. The referenced fix commit maps ENOTSOCK and EBADF to os.ErrClosed. These details let you check the dependency versions and the error-handling implementation.
Official records and device testing
A reply in #3310 linked v1.19.32. The reporter then closed the issue, but had only said they intended to upgrade and test; no post-upgrade device results were published. The evidence comes from official material and pinned source code, without independent reproduction or upgrade-recovery testing on a real device.

After updating the Clash Party core, grant TUN permissions again

Save a few timestamped errors, the actual core version and your CPU observations, then turn off TUN and check whether the repeated errors stop. Use the system proxy temporarily only if the original configuration already supports it. It covers only applications that follow that proxy, not the entire device. Do not leave errors flooding the log just to collect a complete record.

The controls below were checked against source code at Clash Party v2.0.3 and its Chinese labels. Other clients should use their own official core update procedure; do not assume their menus match. Check that your backups are readable and the current configuration still works, then choose a time when a brief loss of connectivity is acceptable.

This section is for standard Mihomo configurations. If you currently use Smart or another core branch and depend on its features, check the original maintainer's compatibility guidance before switching to a specific standard version. Different core names may indicate different capabilities; a higher version number alone is not a reason to replace one with another.

Update the core that is actually running

  1. Open Core Settings and record the current values

    Open core settings from the core card and record the current channel and exact version. Stable, preview, Smart and a specific version are different choices. The Clash Party version in app settings is not the core version.

  2. Choose the official specific version v1.19.32

    In Core Settings, use Choose Specific Version, select v1.19.32, and complete installation. This control uses the project's version-specific source. Check the source and result. Do not switch to Preview or Smart for this fix, and do not import core files from an unknown source.

  3. Manually grant permissions to the Virtual NIC core again

    Replacing the core on macOS may remove its previous permissions. On the Virtual NIC page, use Grant Core Permissions and complete the confirmation shown by your system. Do not simply dismiss the lost-permissions notification or remove system security settings to bypass authorization.

  4. Restart and check the actual core version

    Use Restart core, then check that the core card shows v1.19.32. Once the logs stop repeating, restore and test TUN using the checklist later in this article. A success message or a downloaded file does not establish which version is running.

The ordinary update button and Choose Specific Version perform different actions. A specific version is used here to keep the review target fixed. Check release notes separately for later versions; do not assume that all future versions have been verified. If downloading, checking, granting permissions, or starting fails, stop at that step. Do not keep adding core, subscription, and DNS changes.

If you still need to compare stacks, change only stack and keep the original settings

Complete the confirmed core fix first. If a temporary comparison is still necessary, change only tun.stack from mixed to gvisor in a local override you manage, keeping the original value and a backup. Do not copy this step directly if the original setting is not mixed or the client has no supported override control.

The example below shows only the field to change; it is not a complete configuration. Keep the original DNS, routes, device name, subscriptions, and other TUN settings. After applying the change, check that the final configuration actually running uses gvisor, then restart the core normally. Do not edit the remote subscription or change strict-route at the same time, which would make the result harder to interpret.

For a temporary comparison, change only stack under the existing tun section
tun:
  stack: gvisor

One recovery reported in #3310 involved both a restart and configuration changes. It cannot be attributed to gVisor alone, nor does it prove the problem will not return over time. The official documentation distinguishes the system, gvisor, and mixed implementations; they are not ranked by newer being better. Record changes in the same workload. If there is no improvement, restore the original stack rather than treating the new setting as a permanent answer.

Once the repeated errors stop, check CPU usage and real connectivity

Observe both the core and client processes with the same configuration and a comparable load, then repeat the website or application requests that previously failed. Do not use someone else's CPU numbers as your pass threshold. Compare your own sustained usage and log growth before and after the change, and avoid treating a brief drop as a lasting result.

Repeated logs stopping does not prove that TUN can connect again. If access still fails, keep TUN off. Check that the core has started, permissions are granted and the current profile is applied, then restart normally and repeat the original request. Do not keep increasing the log level or change DNS at the same time to guess at a fix.

Check each item after the fix

  • Confirm the running core is v1.19.32 and record the client version separately
  • Confirm TUN permissions are granted and the original subscriptions and local configuration still load
  • Confirm the same error while reading packets no longer repeats rapidly and log growth is normal
  • Confirm neither the core nor the client continues to use abnormally high CPU under a comparable load
  • Test the original workload, direct and proxied access, and any UDP functionality you actually need separately
  • Test again after a normal core restart, keeping the original channel, stack, and independent backups

If the upgrade or comparison fails, how do you recover and report it?

If you temporarily changed stack, first restore the recorded original value and restart the core. Keep TUN off until basic connectivity returns. If needed, use a system proxy method that previously worked and is supported. Do not assume it covers every application, and do not delete the entire client data directory.

If the new core will not start, use your backups to restore the original channel, exact core version, and configuration, then grant permissions again as the client instructs. The old core may still contain this error loop and should not be used as a lasting solution under conditions known to trigger it. If rollback brings back the repeated errors, turn off TUN, keep a working connection method, and stop retrying. Downgrading the application and restoring configuration are separate operations.

If the problem returns, provide macOS and architecture details, the client and actual core versions, stack, permission status, the earliest usable short error sample, and the differences before and after both restarting and changing settings. Record configuration reloads, waking from sleep, or network changes only as observed; events happening close together do not establish a cause. Before sharing, remove subscription tokens, passwords, private domains, and information that identifies your device.

References