Troubleshooting#
This troubleshooting reference covers common CloudXR.js issues and first-pass diagnostics.
Common Symptoms and Fixes#
WebXR not available or no immersive session#
For HTTP testing on Quest, configure insecure-origin browser flags for your dev URL.
For HTTPS deployments, trust both web app and proxy certificates.
Confirm the exact URL, port, and protocol expected by your hosting mode.
Connection fails before stream starts#
Verify signaling endpoint, protocol (
ws://vswss://), and port.Confirm firewall and NAT rules for required TCP and UDP ports.
If using a proxy, validate target routing and certificate trust.
Signaling connection fails (error 0xC0F22202)#
The sample apps display this as "Signaling connection failed" in the
connection status banner. The code is emitted whenever the WebSocket
signaling channel between the client and the CloudXR Runtime (or its TLS
proxy) cannot be established. The SDK surfaces it via
StreamingError. Closely related codes:
Code |
Meaning |
|---|---|
|
Signaling connection failed (generic—refer to the causes below). |
|
Signaling connection timeout. |
|
Signaling setup failed. |
Common causes, in rough order of likelihood:
TLS certificate not trusted by the client. Browsers reject self-signed certificates whose
subjectAltNamedoes not match the hostname or IP the client reaches. Proxy logs showSSL handshake failure ... certificate unknown. SetCERT_HOSTNAMESto include every reachable address, delete the cachedserver.pem, and restart. Refer to WebSocket Proxy Setup.Browser blocked the request (Private Network Access). A page on a public origin (e.g.
https://...github.io) calling a private-IP proxy needs the user to have granted local-network permission on the calling origin. The proxy already returnsAccess-Control-Allow-Private-Networkwith valuetrue; the missing piece is typically the per-site browser permission.Proxy or runtime not running. Confirm
docker psshows the proxy container, and that the CloudXR Runtime is listening on the backend port (default49100). The proxy logsConnection refuseduntil the runtime is up.Wrong endpoint configuration in the client. Verify
serverIP,serverPort, anduseSecureConnection(or the proxy URL) match where the proxy and runtime are actually listening.Network reachability. Confirm the phone or headset is on the same LAN as the proxy host (no AP isolation, VPN-only routing, etc.). A failed
pingfrom the device shell rules this category in or out.
TLS certificate rejected by client#
Typical symptoms include:
The client browser reports
ERR_CERT_COMMON_NAME_INVALID.The proxy logs
SSL handshake failure ... certificate unknown.
The proxy’s auto-generated certificate covers localhost, 127.0.0.1,
and ::1 only. Modern browsers reject self-signed certificates whose
subjectAltName does not include the hostname or IP the client is
reaching.
Set CERT_HOSTNAMES to include every address the proxy will be reached at
(LAN IP, mDNS hostname, etc.), delete the cached server.pem, and restart
the container. Refer to WebSocket Proxy Setup.
Browser blocks access to a LAN proxy#
Symptom in the browser console:
Permission was denied for this request to access the
localaddress space.
Modern Chromium browsers block requests from a public origin to a private IP
unless the server returns Access-Control-Allow-Private-Network with value true on
its preflight and the user grants local-network permission for the
calling site.
The supplied proxy sends the required response header automatically. If the browser still blocks the request, grant local-network access on the calling origin (the page issuing the request), not on the proxy URL. The simpler dev-time alternative is to host the WebXR application itself on the same private network as the proxy, which avoids the public-to-private boundary entirely.
Media connects but stream is unstable#
Check latency, jitter, and packet loss against Network Setup.
Reduce bitrate and/or stream resolution for constrained networks.
Verify that server GPU and encoder capacity are not saturated.
Hand Tracking Not Responsive#
Pause and resume immersive mode.
Restart the headset if behavior persists.
Confirm runtime and client are both actively streaming.
Connection Issues and Error Categories#
Signaling Errors (WebSocket)#
Typical indicators include connection refusal, timeouts, and signaling-stage failures.
Quick checks:
Verify server or proxy address and signaling port.
Ensure TCP signaling port is reachable.
Confirm firewall allows signaling traffic.
Media Connection Errors (WebRTC and UDP)#
Typical indicators include successful signaling but no media stream.
Quick checks:
Verify UDP media port forwarding and firewall rules.
Verify NAT endpoint or port configuration.
Configure STUN/TURN for restrictive networks.
Other Streaming Errors#
Check network quality and available bandwidth.
Confirm CloudXR Runtime is active and using the expected profile.
Review runtime logs for stream start and stop failures.
Working with Error Codes#
CloudXR.js reports technical error codes with stream failures. Capture the code and include it in bug reports.
onStreamStopped: (error?: CloudXR.StreamingError) => {
if (error?.code) {
const hexCode = '0x' + error.code.toString(16).toUpperCase();
console.error(`${error.message} (${hexCode})`);
}
}
NAT Debug Checklist#
Validate external TCP signaling reachability.
Validate external UDP media reachability.
Confirm runtime is configured with public endpoint and external ports.
If using
mediaAddressin the client, confirm that the runtime was started withenable-icedisabled.Confirm client uses public endpoint values, not private LAN values.
You can also consider STUN/TURN if direct NAT mapping is insufficient for your use case.
NAT Debugging Steps#
Verify signaling port accessibility (TCP):
nc -zv <public-ip> <signaling-port>
Verify media port accessibility (UDP):
nc -zv <public-ip> <media-port>
Bidirectional UDP test:
On the server:
nc -u -l <internal-media-port>
On the client:
echo "test" | nc -u <public-ip> <external-media-port>
Network Performance Checks#
Bandwidth:
iperf3 -s
iperf3 -c <server-ip>
Latency:
ping <server-ip>
If latency, jitter, or packet loss exceed guidance, reduce streaming load and improve Wi-Fi or network quality before further debugging.