{"record":{"id":"d881966a5b0c38ef","repo":"ruvnet/RuView","slug":"http-resp-status","errorCode":null,"errorMessage":"HTTP ${resp.status}","messagePattern":"HTTP \\$\\{resp\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"v2/crates/wifi-densepose-pointcloud/src/viewer.html","lineNumber":509,"sourceCode":"        var fetchTimer = null;\n        var lastBackendError = null;\n\n        function scheduleNextFetch(delayMs) {\n            if (fetchTimer) clearTimeout(fetchTimer);\n            fetchTimer = setTimeout(fetchCloud, delayMs);\n        }\n\n        async function fetchCloud() {\n            // Demo-only mode: never hit the network. Use the normal cadence.\n            if (backendArg === \"demo\" || networkDisabled) {\n                transportMode = \"demo\";\n                handleData(pickDemoFrame());\n                scheduleNextFetch(BASE_INTERVAL_MS);\n                return;\n            }\n            try {\n                var resp = await fetch(buildSplatsUrl(), { cache: \"no-store\" });\n                if (!resp.ok) throw new Error(\"HTTP \" + resp.status);\n                var data = await resp.json();\n                transportMode = (backendArg === \"auto\") ? \"live\" : \"remote\";\n                consecutiveFailures = 0;\n                currentIntervalMs = BASE_INTERVAL_MS;\n                lastBackendError = null;\n                handleData(data);\n                scheduleNextFetch(BASE_INTERVAL_MS);\n            } catch (err) {\n                consecutiveFailures += 1;\n                lastBackendError = err && err.message ? err.message : String(err);\n                if (requireLive) {\n                    document.getElementById(\"stats\").innerHTML =\n                        '<span class=\"demo\">&#9679; OFFLINE</span><br>Live backend required (?live=1) but unreachable.<br><span class=\"label\">' + lastBackendError + '</span>';\n                    // Even strict-live: back off so we don't spam.\n                    currentIntervalMs = Math.min(currentIntervalMs * 2, MAX_INTERVAL_MS);\n                    scheduleNextFetch(currentIntervalMs);\n                    return;\n                }","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/v2/crates/wifi-densepose-pointcloud/src/viewer.html#L491-L527","documentation":"fetchCloud() in the point-cloud viewer throws `HTTP ${resp.status}` when the fetch to buildSplatsUrl() returns a non-2xx response. buildSplatsUrl() resolves to /api/splats for backend=auto or `${backendArg}/api/splats` for an explicit remote backend (and null for demo). The catch increments consecutiveFailures, records lastBackendError, and unless ?live=1 was passed, auto mode sets networkDisabled and falls back to demo frames.","triggerScenarios":"backend=auto but the page is served without the splats API so /api/splats returns 404; a remote ?backend=http://host:port whose service is down or returns 502/503 via a proxy; the backend throwing 500 while generating the splat frame; stale LAN address after the backend host changed.","commonSituations":"Opening viewer.html from a static host or file:// where /api/splats does not exist; the wifi-densepose-pointcloud service crashed while the page keeps polling; wrong port in ?backend=; reverse proxy in front of the backend returning 502.","solutions":["Verify the backend directly: curl the exact buildSplatsUrl() target (e.g. curl -i 'http://host:port/api/splats') and confirm 200 with JSON","Use ?backend=demo for a network-free demo, or remove ?live=1 so auto mode falls back to demo frames on failure","For remote backends, re-check the scheme/host/port in ?backend= (trailing slashes are stripped) and that it serves /api/splats","For 5xx responses, inspect the backend logs (lastBackendError is shown in the stats element) and restart the service"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Before enabling live mode, probe the exact URL the viewer will poll\nasync function splatsBackendReachable(splatsUrl) {\n  if (!splatsUrl) return false;\n  try {\n    const r = await fetch(splatsUrl, { cache: 'no-store' });\n    return r.ok;\n  } catch {\n    return false;\n  }\n}\nconst url = buildSplatsUrl();\nconst live = url ? await splatsBackendReachable(url) : false;\n// open viewer.html with ?backend=demo when !live","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to ?backend=demo for offline demos; use ?backend=auto only where the API is deployed","Never combine ?live=1 with an unverified remote backend — it disables the demo fallback","Watch the stats element: consecutiveFailures and lastBackendError reveal backend loss immediately"],"tags":["http","pointcloud","viewer","fallback"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}