V2Ray Client Troubleshooting Diagnose by Symptom
From no internet, server timeouts and failed subscriptions to speed, DNS, system proxy and mobile issues, split into nine chapters, each with a diagnostic order and fixes.
How this page and the Setup Guide split the work
The setup guide walks the main path once: import a subscription → choose a mode → connect → verify. This page does not repeat those steps; it is organised by symptom, giving a diagnostic order and fixes for each type of problem. If you are installing for the first time, start with the Setup Guide; if you can already connect but something is wrong, pick the matching chapter from the list below.
Symptom Quick Reference
| Symptom you see | Check first |
|---|---|
| Client shows connected, but pages won't open | Chapter 02: local ports, proxy tests and routing rules |
| Log shows timeout / refused / handshake | Chapter 03: server reachability, authentication and TLS parameters |
| Server list is empty, subscription update returns an error | Chapter 04: subscription fetch, group filters and overwrite |
| Connects but is slow and drops frequently | Chapter 05: transport, multiplexing and route comparison |
| A few domains won't open or resolve incorrectly | Chapter 06: DNS configuration, domain sniffing and cache refresh |
| Command line works through the proxy, browser doesn't | Chapter 07: system proxy registration and port conflicts |
| Double-click does nothing, core keeps restarting | Chapter 08: config validation, permissions and security software blocking |
| Android connection drops or gets taken over | Chapter 09: VPN authorization, battery policy and per-app proxy |
01 / Diagnostic BaselinePin the variables first, then rule out layer by layer
The most common mistake in troubleshooting is changing several configuration items at once. Swap the server, protocol, routing and DNS together, and even if the connection recovers you cannot tell which change did the work. Every chapter on this page follows the same order: freeze the current environment, split the chain into segments, and verify starting from the segment closest to the client. Only move on to the next segment once the current one passes.
A complete proxy chain splits into six segments: the application issuing the request, the local inbound port, the local core process, the outbound connection (protocol and transport), the remote server, and the target site. Each segment has checkpoints you can verify independently; the table below lists them together, and the troubleshooting steps in later chapters all revolve around these segments.
| Chain segment | How to verify | Pass criteria |
|---|---|---|
| Local inbound | netstat or lsof to check the port | A process is listening on the recorded port at 127.0.0.1 |
| Local core | Check the first log line and the process status | Core starts without errors and the log keeps outputting |
| Outbound to server | curl from the command line through the local proxy | Response headers from the target site are returned |
| Remote server | Switch to a known working server for comparison | The new server can reach the same site normally |
| System proxy | Check the proxy entry in system settings | Address and port match the client settings |
Before you start, pin down four pieces of information
- Client and core version — the first line of the v2rayN log prints the core name and version. Different cores (V2Fly and Xray) support different ranges of the same configuration, so confirm the core first when you hit a field error.
- Local inbound ports — note the SOCKS and HTTP ports in the settings; every command-line check below uses these two ports.
- Current outbound parameters — protocol (VLESS, VMess, Trojan and so on), transport (tcp, ws, grpc), whether TLS is enabled, and the SNI or Host values.
- System proxy and TUN status — whether the client has written the proxy into the operating system, or is capturing all traffic in TUN mode. The two modes call for completely different approaches.
Also keep a troubleshooting log recording the time of each reproduction, the network environment at the time (Wi-Fi or wired, whether you switched networks), and the configuration items you changed. Most "works sometimes, fails sometimes" problems reveal a pattern in this log — for example, only on one particular network, or only after waking from sleep.
Raise the log level and reproduce once
The default log level usually outputs warnings only, which is not enough detail. Before reproducing a fault, set the level to info or debug, then set it back immediately afterwards so the log file does not keep growing. Every log line carries a timestamp, so you can line it up with system events to the second. The structure of the log and how to read common errors is broken down in How to Read v2rayN Runtime Logs.
Run the core separately from the command line
The log panel in the client interface is essentially the standard output of the core process. After exporting the configuration as config.json, you can run it once by hand from the command line to rule out interference from the interface layer:
# Xray core: validate the config only, do not start the service
xray run -test -config config.json
# Xray core: start in the foreground, logs print straight to the terminal
xray run -config config.json
For the V2Fly core, just swap the commands for v2ray test -config config.json and v2ray run -config config.json; the parameters mean the same thing.
Change only one variable at a time
During troubleshooting, retest and record the result immediately after each change. Once several variables stack up, you cannot attribute the fix even if the problem disappears, and the next time the same symptom appears you start over from scratch.
One last rule of thumb: if several servers in the same subscription time out at once, suspect the local network, the subscription itself or the client configuration first; if only one or two servers time out, suspect the server and the route it sits on. This rule decides whether you head to Chapter 03 or Chapter 04 next.
02 / Symptom OneShows connected, but pages won't open
"Connected" in the client only means the local core process started successfully and the inbound port is listening; it does not mean data can pass through the outbound to the target site. This symptom covers the widest range, and the four steps below narrow it down to a specific segment.
Step 1: confirm the local port is listening
# macOS / Linux
lsof -nP -iTCP:10808 -sTCP:LISTEN
# Windows
netstat -ano | findstr "10808"
No output at all means the inbound did not start. Check whether the client process is actually running and whether the inbound port in the configuration is taken by another program; see Chapter 07 for how to handle it.
Step 2: test the proxy directly with curl, bypassing the browser
curl -x socks5h://127.0.0.1:10808 -I https://www.example.com
curl -x http://127.0.0.1:10809 -I https://www.example.com
The two commands test the SOCKS and HTTP inbounds separately. How to read the results:
- Both return response headers: the proxy chain is fine, so the problem is in the browser or the system proxy layer — go to Chapter 07.
- Neither works: the outbound or the remote end is at fault — go to Chapter 03.
- Only one works: the inbound configuration or protocol type for that port is wrong; check whether both inbounds are enabled in the settings.
The h in socks5h means the domain is resolved by the proxy; without it, the local machine resolves the domain to an IP first and then hands it to the proxy. Testing with socks5h rules out interference from local DNS; the difference between the two is covered in Chapter 06.
Step 3: check whether a routing rule is sending the target out as a direct connection
The common split-routing presets in clients usually include a rule that routes by domain region. If the target domain is judged to be direct and the direct route itself is broken, the browser behaves exactly as if the proxy were not working. To pin it down, set the log level to info, visit the target site, and check whether the outbound tag for that request in the log is direct or proxy.
If it is a misclassification, there are two ways to handle it: add the domain to the proxy rules in the routing settings, or temporarily set the default outbound to the proxy to confirm whether the rule is the cause. A routing rule skeleton you can adapt:
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{ "type": "field", "domain": ["geosite:cn"], "outboundTag": "direct" },
{ "type": "field", "domain": ["geosite:geolocation-!cn"], "outboundTag": "proxy" }
]
}
}
Rules are matched from top to bottom and the first hit wins, so more specific entries must come first. This topic is covered in more depth in Routing Rules in Practice.
Step 4: compare against a direct connection to rule out a problem with the target site itself
Visit the same site over a network that does not go through the proxy. If the direct connection fails too, the problem is not in the client and there is no point changing more settings. This step looks trivial, but it heads off a fair number of cases where you troubleshoot for ages only to find the site itself is down.
| curl test result | Conclusion | Next step |
|---|---|---|
| Both work, browser doesn't | System proxy or browser layer | Chapter 07: check system proxy registration and ports |
| Neither works | Outbound or remote end | Chapter 03: reachability and handshake parameters |
| Proxy works but the target site does not respond | Routing misclassification or site outage | Check the routing log and compare with a direct connection |
Port types are not interchangeable
The SOCKS port and the HTTP port cannot be swapped. Put the HTTP port into an application that only accepts SOCKS, or the other way round, and the symptom is always "the connection is established but pages won't open".
03 / Symptom TwoServer timeouts and handshake failures
What these problems have in common is that the local core is already working but data cannot get out. The log shows clear error lines, so classify by keyword first and then decide which direction to investigate — far faster than changing settings one by one.
Log keyword reference
| Log keyword | Usual meaning | Check first |
|---|---|---|
i/o timeout、context deadline exceeded | The connection to the server was not established within the timeout | Server address and port reachability, local network egress |
connection refused | Nothing is listening on the target port | Whether the server side is running, whether the port number is wrong |
EOF、connection reset by peer | The connection was dropped after being established | Mismatched transport parameters, interference from middleboxes |
tls: handshake failure, certificate-related messages | The TLS handshake did not complete | SNI, certificate, REALITY public key |
invalid user、rejected | Authentication failed | UUID or password, system clock skew |
Test reachability first, then suspect the configuration
# Linux / macOS: test whether a TCP port can be connected to
nc -vz 203.0.113.10 443
# Windows PowerShell
Test-NetConnection -ComputerName 203.0.113.10 -Port 443
The address in the example comes from a documentation-only range; replace it with your own server address and port when you use it. How to read the result:
- Port unreachable: the server is not listening, the server-side firewall is blocking, or the route is unreachable. Confirm the server state first, then consider changing the port or the route.
- Port reachable but the client still reports a timeout: check whether the address in the client is a domain or an IP. If it is a domain, resolution may be the problem — go to Chapter 06.
- ICMP ping failing does not mean the port is unreachable. Most servers do not answer ping by default, so go by the TCP test result.
Authentication parameters and clock skew
The VMess protocol uses a timestamp in authentication, and the server rejects the connection outright when the clock difference between client and server exceeds the allowed range. Check whether automatic time synchronisation is enabled; virtual machines and dual-boot devices commonly drift after long sleep periods. Credential fields such as UUID and password are case-sensitive, and it is easy to drop trailing characters when copying.
TLS and transport parameters
- For servers with TLS enabled, the SNI must match the server certificate; a wrong value produces a handshake failure.
- REALITY servers need the correct serverName and public key (publicKey); both are required. How these two parameters work is explained in REALITY and XTLS Vision Explained.
- With ws or grpc transport, path and host must match the server side and are case-sensitive.
- The host field of the transport layer and the SNI of TLS are two different parameters — do not mix them up.
Re-import the share link once
The easiest way to rule things out is to import the server share link again. Manual transcription easily drops case or special characters, and a fresh import eliminates that class of error in one go.
If several servers time out at once and the reachability tests all fail, shift your suspicion from the individual server to the local network egress or the subscription itself; if only one server times out at fixed times of day, note the pattern and check with the service provider.
04 / Symptom ThreeSubscription update failures and abnormal server lists
The subscription is the source of the server list. A failed update shows up as all servers disappearing, the list stuck on old content, or an error dialog after the update button spins. Confirm whether the subscription content itself can be fetched first, then look at the client side — do not reverse the order.
Step 1: fetch the subscription once from the command line
curl -L -A "v2rayN" -o sub.txt "https://example.com/api/v1/client/subscribe?token=xxxx"
head -c 300 sub.txt
The first command saves the subscription content to a file; the second prints the first 300 characters so you can judge the response format:
- Returns a base64 string: this is the normal encoding for a server list, so the problem is on the client side.
- Returns an HTML page: the subscription URL has expired, or the request was intercepted by a middlebox and redirected to an error page.
- Returns 404 or 403: the address has expired, the token is wrong, or the server restricts the User-Agent. The
-A "v2rayN"in the example sets the User-Agent; some servers use it to tell where requests come from.
You need a server before you can update a subscription
If the subscription server is only reachable through a proxy and the client currently has no working server, you fall into a loop: no server → cannot update the subscription → still no server. There are two ways out: enable "update subscription through proxy" in the subscription settings and import one working server by hand first; or complete one update on a network that can reach the subscription server directly, then switch networks once the servers are imported.
Servers disappear or shrink after an update
- Group filters: check whether a group filtered by name or region is set; filtered-out servers are not displayed.
- Overwrite: some clients replace the whole group on subscription update, so manually added servers should live in a separate group to avoid being overwritten.
- Deduplication: multiple routes to the same server are merged into one after import, so a lower count is normal.
- Server-side changes: the subscription content itself changed; go by the latest fetch.
Automatic vs manual updates
The update interval in the settings determines how often automatic updates run. Manual updates usually have two entry points: a full update re-fetches and overwrites the server list, while refreshing only the subscription content leaves the currently selected server untouched, which suits keeping things as they are while the connection is stable. During troubleshooting, turn automatic updates off first so background tasks do not interfere with your judgement.
| Response content | Diagnosis | Action |
|---|---|---|
| base64 string | Subscription is fine | Check the group and update entry on the client side |
| HTML page | Address expired or request intercepted | Ask the provider for the new address |
| 404 / 403 | Wrong token or restricted source | Check the address and retry with a different User-Agent if needed |
| Connection timeout | The current network cannot reach the subscription server | Switch networks, or enable update through proxy |
A subscription URL is as sensitive as a credential
Subscription URLs usually carry a token and are equivalent to account credentials. Before posting a screenshot or a forum message, make sure the address is redacted — never paste it in full.
05 / Symptom FourConnects but is slow and drops frequently
"Slow" covers at least four different behaviours: slow handshake (a long wait before the page opens), low bandwidth (download speed won't climb), jitter (fast then slow), and dropouts (the connection breaks). Each calls for a different approach, so match your case before you start changing things.
It also helps to separate three common latency figures: ping measures the ICMP round trip, real connection latency measures how long the proxy chain takes to establish, and a download speed test measures actual throughput. They measure different things and cannot substitute for one another. Comparing the Three Latency Measurements sets out when each figure applies and how it is commonly misread.
Start with a direct-connection comparison
On the same device, at the same time of day, download a large file from a same-region address without going through the proxy and record the speed. If the direct connection is unstable too, the problem is in the local network or the ISP egress, and further client tuning is pointless.
Confirm the traffic really goes through the proxy
Check the outbound tag for the target domain in the log. Slow speeds are sometimes caused by a rule sending the target out as a direct connection, and the direct route happens to be congested — which looks like "the proxy is slow".
Transport and multiplexing
- Multiplexing (mux): merging several connections onto one TCP connection cuts handshake overhead on low-loss routes; on high-loss routes, one bad connection drags down every request multiplexed onto it. Test with it on and off.
- Transport: tcp is the most direct; ws and grpc are more stable on certain networks but add a layer of encapsulation and its overhead.
- Encryption algorithm: throughput differs noticeably between algorithms on weaker devices, so try switching and compare.
MTU and fragmentation
When large packets are dropped on the route, the typical symptoms are "pages open but downloads stall" or "video takes a long time to buffer". Reduce the MTU step by step at the client or system level, by 8 to 16 bytes each time, and watch for improvement. Reconnect once after the change for it to take effect.
Common causes of dropouts
- Server load changes or a route switch;
- Local network switching: moving between Wi-Fi and wired, or a mobile network changing cell towers;
- The proxy process ends up in a bad state after the system sleeps and wakes, and needs one reconnect;
- Long-idle connections are cleaned up by middleboxes and recover after reconnecting.
| Symptom | Suspect first | How to verify |
|---|---|---|
| Long wait before pages open | Handshake overhead, multiplexing settings | Toggle mux and compare, watch real connection latency |
| Download speed won't climb | Route bandwidth, encryption algorithm | Switch servers and compare with a direct connection |
| Fast then slow | Route congestion, packet loss | Run speed tests at several fixed times and compare |
| Connection breaks frequently | Network switching, sleep and wake | The time pattern in your troubleshooting log |
Run speed tests at fixed times
The same route performs very differently at peak hours and in the small hours, so a single result proves nothing. Take at least three measurements at different times before drawing a conclusion.
06 / Symptom FiveSome domains resolve incorrectly
The typical pattern: most sites work, a few domains won't open; or the resolved IP does not match the real one; or sites in a particular region show noticeably higher latency. What they share is that the problem sits at the step where a domain becomes an IP.
Where a domain gets resolved
When you use a SOCKS proxy, where the domain is resolved depends on the client settings:
socks5h(with the h) or domain sniffing enabled: the domain goes to the core and is resolved according to the DNS configuration;socks5(without the h): the local machine resolves it to an IP first and then hands it to the proxy, so local DNS problems are carried straight into the proxy chain.
When troubleshooting, test once with socks5h first — it quickly separates "a local DNS problem" from "a proxy chain problem".
Adjust the client's DNS configuration
{
"dns": {
"servers": [
{ "address": "1.1.1.1", "domains": ["geosite:geolocation-!cn"] },
{ "address": "223.5.5.5", "domains": ["geosite:cn"] }
]
}
}
This configuration sends domains from different regions to different DNS servers, cutting the extra latency of cross-region resolution. Restart the core process after the change for it to take effect.
Routing rules need domain information to match
Domain-based routing rules need the domain first. If traffic enters the core as an IP, domain rules cannot match and the request falls through to the default outbound. With domain sniffing enabled, the core can recover the domain from HTTP requests and TLS handshake information:
{
"inbounds": [
{
"tag": "socks-in",
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"sniffing": { "enabled": true, "destOverride": ["http", "tls"] },
"settings": { "udp": true }
}
]
}
Once sniffing is on, domain rules and domain-based routing work as intended. If a rule "is clearly written but does not take effect", check whether sniffing is enabled first.
Targeted fixes for a single domain
If only a few domains resolve incorrectly, you can hard-code the correct address in the hosts configuration, or point that domain at a specific server in the DNS configuration. The smaller the change, the easier it is to verify and the less likely it is to introduce new problems.
Flush the system DNS cache
# Windows
ipconfig /flushdns
# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux(systemd-resolved)
sudo resolvectl flush-caches
| Symptom | Possible cause | Action |
|---|---|---|
| A few domains won't open | Abnormal resolution result | Hard-code in hosts or set a dedicated DNS server |
| Domain rules do not take effect | Sniffing is not enabled | Enable sniffing in the inbound configuration |
| No change after editing the config | DNS cache not flushed | Restart the core and flush the system cache |
| High latency to sites in one region | Cross-region resolution | Split DNS servers by region |
The DNS section needs a restart to take effect
After changing the DNS configuration you must restart the core process; some clients do not hot-reload the DNS section, so clicking save in the interface shows no change.
07 / Symptom SixSystem proxy not working and port conflicts
The typical pattern: the client shows connected, the browser won't open pages, but curl from the command line through the local proxy works. That means the proxy chain itself is fine and the problem is that the system proxy was not written, was written in the wrong place, or the port does not match.
Where to check the system proxy on each platform
| Platform | Where to check |
|---|---|
| Windows | Settings → Network & Internet → Proxy; or Internet Options → Connections → LAN settings |
| macOS | System Settings → Network → current service → Details → Proxies |
| Linux | The desktop environment's network proxy settings, or the http_proxy / https_proxy / all_proxy environment variables in the shell |
Common reasons the system proxy won't stick
- The client lacks the permissions to change system proxy settings;
- Another proxy application is running and holds the same setting;
- The browser uses its own proxy configuration or a proxy extension and ignores system settings;
- The system proxy only affects applications that read system settings; some applications need TUN mode to be captured.
TUN mode vs system proxy
| Item | System proxy | TUN mode |
|---|---|---|
| Scope | Applications that read system proxy settings | All traffic, with rule-based exclusions |
| Permissions | Normal permissions, with a one-time authorisation on some platforms | Requires administrator or root privileges |
| Typical problem | Applications that ignore system settings | Routing table conflicts, contention with other VPNs |
Port conflicts
# Windows: find the process ID holding the port
netstat -ano | findstr ":10808"
tasklist | findstr "<PID>"
# macOS / Linux
lsof -nP -iTCP:10808 -sTCP:LISTEN
Once you have found the process, end it, or change the client's inbound port to another free one.
The full sequence after changing the port
- Change the inbound port in the client settings and save;
- Turn the "system proxy" switch off and on again so the new port is written to the system;
- Check in system settings that the proxy address and port match;
- Verify once with curl through the new port to confirm the chain works.
Common sources of port conflicts
A previous client process did not exit cleanly, another proxy application occupies the same port range, or a development tool or local service happens to listen on the same port. Before changing the port, identify who holds it — do not just pick a different number blindly.
08 / Symptom SevenClient startup failures and corrupted configuration
The symptoms are a double-click that does nothing, an immediate exit after launch, or a normal interface with a core that keeps restarting. First work out whether "the client interface won't start" or "the core process won't start" — the two call for different investigations.
Validate the configuration syntax first
# Xray core: validate the config only, do not start the service
xray run -test -config config.json
# V2Fly core
v2ray test -config config.json
Common errors and what they mean:
invalid character: there is an illegal character in the JSON, usually a trailing comma, a comment or a full-width quotation mark;unexpected end of JSON input: a bracket or quote was not closed;unknown field: the field name is misspelled, or the current core does not support that field.
Comments and trailing commas in a configuration both cause parsing to fail, and copying config snippets from elsewhere is the most common way to bring them in.
The core keeps restarting
The interface says running, but the log shows the core process starting and exiting repeatedly — usually a failed configuration validation or a port conflict. Set the log level to debug, look at the last line before each exit, then follow the procedures in Chapter 03 and Chapter 07.
Permissions and paths
- When the installation directory sits under a system-protected directory, writing the configuration needs administrator rights; you can move the data directory into your user directory instead;
- When the path contains special characters or is very deep, some system components fail to read it;
- After moving the configuration file, the old path recorded by the client no longer works.
Security software blocking
Some security software flags the proxy core as a risky program and blocks it silently. The typical sign is a process that disappears a few seconds after launch, while running the same configuration by hand from the command line works fine. The fix is to add an exception for that directory in the security software, or try a different installation directory. The first-time installation flow on Windows and its common pitfalls are covered step by step in Installing v2rayN on Windows.
Configuration backup and restore
Export the configuration before you change it. When startup problems appear, use the reset function to return to the default configuration and then restore items one by one — that pinpoints which configuration item caused the problem. Importing servers by hand is safer than restoring the whole configuration directory and easier to roll back.
| When it crashes | Common cause | Action |
|---|---|---|
| Nothing happens on double-click | Security software blocking, insufficient permissions | Add an exception or run once as administrator |
| Exits immediately after launch | Configuration syntax error | Validate the configuration with -test and fix the JSON |
| Interface fine, core keeps restarting | Port conflict or unsupported field | Change the port, check the fields the core supports |
| Appears only after a config change | The newly added configuration item is wrong | Roll back to the last working configuration |
09 / Symptom EightAndroid-specific troubleshooting
Android runs v2rayNG (Xray core) and v2flyNG (v2fly core). They work differently from the desktop: the phone captures traffic in VPN mode and there is no "system proxy" layer, so some desktop troubleshooting steps do not apply on mobile — and vice versa.
Differences between the two clients
| Item | v2rayNG | v2flyNG |
|---|---|---|
| Core | Xray | v2fly |
| Positioning | First choice, faster support for new protocol parameters | Alternative, consistent with the v2fly ecosystem |
| Configuration scope | Supports Xray extension fields | Limited to what v2fly supports |
The same share link imports into both, but a few newer protocol parameters only take effect on the Xray core. When something "imports but won't connect", try the other client once — it quickly tells you whether the problem is the parameters or the client. Both installers are in the Android section of the download page.
Common reasons it won't connect
- VPN authorisation dialog not confirmed: the system shows an authorisation dialog on first connect and you must allow the VPN connection;
- Another VPN app is already running: only one VPN tunnel is allowed at a time;
- Battery policy: the app is killed in the background by the system, shown by the notification icon disappearing and the connection dropping;
- Per-app proxy: only some apps are ticked, and unticked apps do not go through the proxy.
Subscriptions and server management
When a subscription update fails on the phone, switch networks and try again: swap mobile data and Wi-Fi once. A change in server order after an update is normal — go by the subscription content. Subscription URLs carry a token, so do not post screenshots in public. Server list management matches the desktop, and the subscription failure flow in Chapter 04 applies directly.
Logs and self-checks
The log page in v2rayNG shows the core output, and the approach matches the desktop: look at the error line for the timestamp first, then tell apart timeout, authentication and DNS problems. There is no command-line environment on mobile, so verification relies mainly on switching servers and switching networks for comparison.
| Check | Desktop | Android |
|---|---|---|
| Traffic capture | System proxy or TUN mode | VPN mode, no system proxy layer |
| Port checks | netstat / lsof for inbound ports | Not applicable, assigned by the system |
| Background survival | Suspended when the system sleeps | Affected by battery policy, needs whitelisting |
| Verification | curl from the command line through the local proxy | Switch servers and networks for comparison |
Do not run two proxy apps at the same time
Android allows only one VPN tunnel, and the one started later takes over from the earlier one — which looks like "the first app disconnected for no reason". Before troubleshooting, confirm that only one proxy app is running on the system.
If none of the nine chapters covers your case, sum the situation up in one sentence: what you did, when it happened, and what the last line of the log says. The FAQ page collects more detailed Q&A by topic, and the glossary page helps you check what the terms in the log mean.