Troubleshooting
Which tool to use
BEFORE INSTALL → meridian preflight IP
"Will this server work for Meridian?"
Tests: SNI reachability, port 443, DNS, OS, disk space.
AFTER INSTALL, CAN'T CONNECT → meridian test IP
"Is the proxy reachable from where I am right now?"
Tests: TCP port 443, TLS handshake (Reality), domain HTTPS.
No SSH needed — runs from the client device.
AFTER INSTALL, SOMETHING BROKE → meridian doctor IP
"Collect everything for debugging."
Collects: server OS, Docker, 3x-ui logs, ports, firewall, SNI, DNS.
Add --ai to preflight or doctor for an AI-ready diagnostic prompt.
Can’t connect at all
Port 443 not reachable
Causes:
- Cloud provider firewall / security group blocks port 443 inbound
- ISP or network blocks the server IP entirely
- Server is down or proxy is not running
- UFW on the server doesn’t allow port 443
Fixes:
- Check cloud provider console — ensure port 443/TCP is allowed inbound
- Try from a different network (mobile data, another Wi-Fi)
- SSH in and check:
docker ps(is 3x-ui running?),ss -tlnp sport = :443 - Check UFW:
ufw status— should show 443/tcp ALLOW
TLS handshake fails
Causes:
- Xray is not running inside the Docker container
- Port 443 is occupied by another service
- Reality SNI target is unreachable from the server
Fixes:
- Check Xray:
docker logs 3x-ui --tail 20 - Check port:
ss -tlnp sport = :443— should be nginx - Test SNI:
meridian preflight IP
Domain not reachable
Causes:
- DNS not pointing to server IP
- nginx not running or failed to get TLS certificate
- nginx not routing domain SNI correctly
Fixes:
- Check DNS:
dig +short yourdomain.com @8.8.8.8 - Check nginx:
systemctl status nginx - Check nginx config:
/etc/nginx/conf.d/meridian-stream.conf
Connection drops after seconds
Causes:
- System clock skew >30 seconds between client and server
- MTU issues on the network path
- ISP resetting long-lived TLS sessions
Fixes:
- Server:
timedatectl set-ntp true. Client: enable automatic date/time - Try a different network
- Use WSS/CDN connection (domain mode)
Setup fails
Port 443 conflict
Another service (Apache, Nginx) is using port 443. Stop it or use a clean server. meridian preflight will tell you what’s using the port.
Docker installation fails
Conflicting Docker packages from distro repos. Meridian auto-removes them, but if Docker is already running with containers, it skips to avoid disruption.
SSH connection errors
Test SSH manually: ssh root@SERVER_IP. Ensure you have key-based access. Use --user flag if not root.
Xray fails to start (invalid JSON / MarshalJSON error)
The 3x-ui inbound settings or streamSettings fields contain corrupted JSON. This happens when settings is sent as a nested object instead of a JSON string — the 3x-ui Go struct expects a string type. The API returns success: true but stores only the first key name instead of the full JSON.
Fix: Uninstall and reinstall: meridian teardown IP && meridian deploy IP. To verify the database: sqlite3 /opt/3x-ui/db/x-ui.db "SELECT settings FROM inbounds;" — each field should be valid JSON.
XHTTP inbound creation fails (port conflict)
In older versions (pre-v3.6.0), both Reality and XHTTP tried to use port 443. 3x-ui rejects duplicate ports.
Fix: Update to v3.6.0+. XHTTP now runs on a localhost-only port, routed through nginx.
Disk space insufficient
Less than 2GB free. Free up space: docker system prune -af, journalctl --vacuum-time=1d, check /var/log/.
DNS resolution fails (domain mode)
Domain doesn’t resolve to server IP yet. Update the DNS A record. Propagation is usually 5-15 minutes (up to 48 hours). Meridian warns if DNS doesn’t resolve but lets you proceed.
Was working, now stopped
Most common cause: Server IP got blocked. Run meridian test IP — if TCP fails, the IP is likely blocked.
See the IP Blocked Recovery guide for step-by-step recovery options (new server, relay swap, CDN fallback).
Other causes:
- Server rebooted and Docker didn’t auto-start →
docker start 3x-ui - Disk full →
df -h /,docker system prune -af
Slow speeds
- Choose a server geographically closer (Finland, Netherlands, Sweden for Europe/Middle East)
- Check server load:
htoporuptime - Try WSS/CDN link — may have better routing through Cloudflare
- Verify BBR is enabled:
sysctl net.ipv4.tcp_congestion_control
Do NOT run other protocols (OpenVPN, WireGuard) on the same server — it flags the IP.
AI-powered help
meridian doctor --ai
Copies a diagnostic prompt to your clipboard for use with any AI assistant.
Or collect diagnostics for a GitHub issue:
meridian doctor
Relay not working
See the Relay guide — Troubleshooting section for relay-specific issues (port conflict, firewall, exit unreachable, service not started).
Interpreting preflight output
| Check | What It Tests | If It Fails |
|---|---|---|
| SNI target reachability | Can the server reach the camouflage site? | Server’s outbound is restricted. Try a different SNI with --sni |
| SNI ASN match | Does the SNI target share a CDN/ASN with the server? | Use a global CDN domain. Avoid apple.com (Apple-owned ASN) |
| Port 443 availability | Is port 443 free or used by Meridian? | Another service is on 443. Stop it or use a clean server |
| Port 443 external reachability | Can the outside world reach port 443? | Cloud firewall blocks it. Open port 443/TCP inbound |
| Domain DNS | Does the domain resolve to server IP? | Update DNS A record |
| Server OS | Is it Ubuntu/Debian? | Other distros may work but are untested |
| Disk space | At least 2GB free? | Free up space |
Interpreting doctor output
| Section | What to Look For |
|---|---|
| Local Machine | OS compatibility |
| Server | OS version, uptime (recent reboot?), disk/memory usage |
| Docker | Is 3x-ui container running? Status should be “Up” |
| 3x-ui Logs | Error messages, “failed to start” entries, certificate issues |
| Listening Ports | Port 443 should show nginx. If missing, proxy isn’t running |
| Firewall (UFW) | Port 443/tcp should be ALLOW. If not listed, it’s blocked |
| SNI Target | Should show CONNECTED with a certificate chain |
| Domain DNS | Should resolve to server IP |
Interpreting test output
| Check | Pass | Fail |
|---|---|---|
| TCP port 443 | Server is network-reachable | Firewall, ISP block, or server down |
| TLS handshake | Reality protocol is working | Xray not running, port conflict, or SNI issue |
| Domain HTTPS | nginx working | DNS or nginx issue |
If all checks pass but the VPN client still can’t connect: re-scan the QR code, check device clock is accurate (within 30 seconds), or try a different app (v2rayNG, Hiddify).