Use this guide if v2rayN reports that Xray failed to start, exits immediately after launch, or cannot load a custom config. Save the full error chain, check listening ports, test the config with the actual Xray binary, then verify fields and version compatibility. Includes Windows commands for finding port usage and a minimal local config to distinguish client, config, and system issues.
1. First, distinguish a startup failure from a connection failure
A page that won’t load doesn’t necessarily mean Xray failed to start. At launch, Xray reads the config, builds inbounds and outbounds, and opens listening ports; a failure at any of these steps can make the process exit immediately. Remote connection timeouts, authentication failures, and TLS handshake errors after Xray is running require a different troubleshooting path. Identify the stage first to avoid repeatedly changing node settings that are already correct.
v2rayN is the client interface; Xray is the core that handles connections. A running interface doesn’t prove the core is working. Menu locations can vary by version. The steps below use a typical Windows desktop layout; if an item has a different name, look for the function described in parentheses rather than applying another client’s menu instructions.
-
Save the error details
Expand the information or log panel at the bottom of the main window and note when the startup attempt occurred. Copy the entire error chain starting with
Failed to start, including the subsequent content separated by>; the last entry is usually more specific than the summary at the top. -
Verify the core
Open “Settings” → “Parameter Settings” → “Core Type” and check that the selected core matches the current node protocol. Some versions use a “Core Type Settings” tab. Then check the executable path in the startup log to confirm that Xray is actually being launched.
-
Reproduce the issue once
Temporarily disable TUN, leave only one v2rayN instance running, select the original node, and restart the service once. Don’t keep switching nodes and flooding the log. Keep about 10 seconds of logs from before and after the restart to confirm that the error belongs to the same startup attempt.
-
Track your changes
Note what changed since the last successful startup, such as local ports, routing rules, custom config, or core files. Back up the current settings, change one variable at a time, and record the result of each test.
2. Port conflicts: find the process listening before changing ports
If the error includes failed to listen or address already in use, check the local listening port first—not the remote server’s port 443. Windows may also show the message Only one usage of each socket address. Common causes include an old core process that hasn’t exited, multiple client instances, or another app using the same address and port.
The examples below use TCP port 10808; not every version of v2rayN uses this default. First, check the actual local listening port under “Settings” → “Parameter Settings” → “Basic Settings,” then replace the number in the commands. A single port can accept multiple proxy protocols when using a mixed inbound, so there’s no need to split it into two ports.
netstat -ano -p tcp | findstr ":10808"
powershell -NoProfile -Command "Get-NetTCPConnection -State Listen -LocalPort 10808 | Select-Object LocalAddress,LocalPort,OwningProcess"
- In the
netstatoutput, look for a row where the local address ends in:10808and the state isLISTENING. The last column shows the PID. ATIME_WAITentry alone does not prove there’s a listening conflict. - If the PID is
4260, runtasklist /FI "PID eq 4260"to see the process name. This PID is only an example; use the value you actually find. - If the process is a core launched by another v2rayN instance, exit that client normally from its tray menu, then check again. Don’t terminate every process with the same name without checking which client it belongs to.
- If the port belongs to an app you need to keep, change the local listening port to an unused one, such as
10818, save, and restart the service. Update the port in any apps where you configured the proxy manually.
Error: bind: address already in use
Cause and fix: The target listening address and port are already in use. Find the PID using the port shown in the error, exit the process normally, or change the current inbound port and restart.
Error: bind: permission denied
Cause and fix: The system refused the bind; this doesn’t necessarily mean another process is listening. Check the listening address, port permissions, and security software. If Windows reports an access-related error, check the system’s excluded port ranges too—don’t just keep terminating processes.
If Windows shows no process listening but still reports that socket access was denied, run netsh interface ipv4 show excludedportrange protocol=tcp to view excluded IPv4 TCP port ranges. If the port falls within one of them, choose an available port outside the range; don’t delete system reservations. Check the relevant permissions only if the log points to TUN or an access issue.
3. JSON syntax: test offline with the actual core
Being able to open a config in a text editor doesn’t mean Xray can parse it. A missing comma, curly quotes, or an unclosed bracket can stop parsing. Syntax errors often include a line number or character position, or messages such as invalid character and unexpected EOF. Exact wording varies by core version and how the config is loaded.
Stop the relevant service in the client, then go to the Xray program directory shown in the log and use the executable there to test a saved copy of the config. The example below uses Windows PowerShell; check.json is the file being tested. This test doesn’t start a proxy listener, but it may still access local files referenced by the config, such as certificates and routing data.
.\xray.exe version
.\xray.exe run -test -config .\check.json
| Error clue | Check first | Fix |
|---|---|---|
invalid character | The reported line and the one before it | Use straight double quotes, and check the colons between keys and values and the commas between items. |
unexpected EOF | End of file and copied content | Make sure the file isn’t truncated, and match each object brace and array bracket. |
cannot unmarshal | Value types | Check whether each value should be a string, number, boolean, object, or array—not just punctuation. |
| Test passes, but startup still fails | Runtime resources | Check port binding, file permissions, and the actual config path. A successful test doesn’t guarantee that Xray can listen on a port. |
The reported line often marks where the parser detected the problem, not where it began. If line 24 is flagged, check line 23 as well. Don’t paste a full config containing credentials into an online formatter; your editor’s bracket matching and the core’s test command are usually enough.
Bottom line: a test only applies to the file you tested
If a manual test succeeds but the client still fails, compare the config path, core path, and working directory in the startup log. Don’t assume the config currently generated by the client is valid just because a different config passed.
4. Config fields: check the hierarchy, not just the spelling
Valid JSON syntax is only the first step; the config must also match Xray’s structure. inbounds and outbounds are arrays; protocol-specific parameters belong in the corresponding settings; transport and security parameters usually go under streamSettings. Putting a field at the wrong level can prevent the config from being built or leave a setting unapplied, even when the JSON is valid.
Don’t paste a config snippet for one core directly into a different config format. The node editor in v2rayN is not a complete Xray JSON config either: the client generates the running config from the node, routing, and global options. In particular, VLESS and VMess use different protocol parameters; don’t swap their entire settings blocks just because both use a user ID.
- Check key names: The S in
streamSettingsis uppercase. Inrouting.rules, the field that references an outbound tag isoutboundTag. Match capitalization to the config requirements of the core you’re using. - Check tags: A rule’s
outboundTagshould match thetagof an outbound. A typo can affect outbound selection after a rule matches; passing a config test alone doesn’t prove that routing works. - Check values:
protocol, the transport type, and the security type must use values recognized by the current core. Using explanatory text as a parameter value can trigger an unknown protocol or type error. - Check resources: If Xray can’t read
geoip.dat,geosite.dat, or a certificate file, check the resource directory, filename, and permissions. Relative paths depend on the actual working directory, so running from another directory can produce a different result.
Error: unknown config id
Cause and fix: The current build doesn’t recognize a protocol or config type in the error chain. Check the specific value that follows, including its spelling, location in the config, and whether the core supports it. Don’t just change the JSON brackets.
Error: no such file or directory
Cause and fix: A file referenced by the config or a required startup resource is missing. Find the specific path in the error chain and confirm the file exists in the runtime environment. If the log mentions routing data, check the resource path before changing routing rules.
Note that some parsing paths may silently ignore unknown fields rather than report an error. So “no error” only means the current check passed—it doesn’t prove every manually entered field took effect. After changing routing, verify outbound selection with a specific target domain; don’t treat one accessible webpage as a complete test.
5. Minimal config: separate environment issues from node issues
If your full config is long, save the example below as check.json. It provides a SOCKS inbound only on the local machine at 127.0.0.1:10818 and connects directly to the destination. It contains no remote proxy node and can’t verify whether a subscription works. Use it to check whether the current Xray can read a config, build an outbound, and open a local port.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "local-check",
"listen": "127.0.0.1",
"port": 10818,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
]
}
- First, run
.\xray.exe run -test -config .\check.json. If it fails, save the output and check the file and current core first. Don’t add real node settings. - After the test passes, run
.\xray.exe run -config .\check.json. The bind test passes only if the process keeps running and127.0.0.1:10818is listening. No new output in the window for a while doesn’t mean the process is stuck. - Stop the test process with
Ctrl+C, then restore the original config one section at a time: node outbound first, then transport and security settings, followed by routing and rule data. Test after each addition. - If the minimal config starts but adding a section makes it fail, focus on the newly added fields or dependencies. Don’t replace the node, port, and core in the same troubleshooting step.
6. Version compatibility: verify which executable is actually running
The client version and core version are separate. Updating v2rayN doesn’t mean Xray was updated, and manually replacing a core file doesn’t guarantee the client is using it. Check the path in the startup log and the output of xray.exe version, and note the processor architecture.
New fields, transport types, and changes to existing fields can all depend on the core version. If you suspect a version issue, keep a copy of the last working version and config, then use the client’s update feature or download center to get a compatible component. Don’t keep deleting fields until the config starts if doing so changes the connection behavior you need.
- Config incompatibility: If the program runs and reports a config error, check which fields and parameters that version supports. Use the core’s test output to narrow it down instead of guessing based on release dates.
- Executable won’t run: If the system says the program can’t run or the executable format is invalid, check the Windows and processor architectures, whether the download is complete, and whether security software quarantined the file. JSON parsing hasn’t started yet.
- Rollback after an update: Exit the client and any remaining core processes, then restore the full matching backup. If the new client still generates a newer config format, reverting only the core may not fix the problem.
- Android comparison: v2rayNG uses the Xray core, while v2flyNG uses the v2fly core. Their supported features aren’t interchangeable, and Windows process lookup commands don’t apply directly to Android.
Bottom line: keep a reproducible set of diagnostics
Record the client version, actual core version, config path, full first error chain, and most recent change. If the minimal config starts, note which added section caused the failure. This is far more useful for diagnosis than a screenshot that only says “startup failed.”
7. Common questions about startup failures
Why does the generated config revert after I restart?
v2rayN regenerates the running config from the node and global options. Change the source settings under “Settings” → “Parameter Settings,” in the node editor, or in routing settings. If you need to write a complete JSON config manually, use the client’s custom config feature and confirm the path of the file it actually loads.
The config test passed. Why does startup still fail?
run -test doesn’t confirm that Xray can bind to a port. Check the actual inbound port first, then confirm the client is using the same core and config as the command-line test. Next, check access to paths for log files, routing data, and other resources; only then investigate other system-level causes.
It works with another node. Does that mean the subscription is broken?
Not necessarily. Nodes can use different protocols and transport settings, and the client may map them to different cores. Keep the failing node and compare its protocol, transport, security type, and core selection in the node editor to find which settings trigger the config error. You don’t need to delete the entire subscription group first.
Running as administrator fixed it. Should I always do that?
First, find out whether the failure occurs during normal local listening or TUN initialization. A regular high-numbered loopback port usually doesn’t require administrator access; if the issue is directory permissions, fix access to that directory. Grant TUN permissions only when needed by the client, rather than using elevation to mask every error.