{"record":{"id":"d0b0421eebcc4264","repo":"decolua/9router","slug":"unsupported-platform-platform","errorCode":null,"errorMessage":"Unsupported platform: ${platform}","messagePattern":"Unsupported platform: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/tunnel/cloudflare/cloudflared.js","lineNumber":49,"sourceCode":"    x64: \"cloudflared-linux-amd64\",\n    arm64: \"cloudflared-linux-arm64\"\n  }\n};\n\n// Fallback order: prefer smallest/most-compatible binary per platform\nconst PLATFORM_FALLBACK = {\n  darwin: \"cloudflared-darwin-amd64.tgz\",\n  win32: \"cloudflared-windows-386.exe\",\n  linux: \"cloudflared-linux-amd64\"\n};\n\nfunction getDownloadUrl() {\n  const platform = os.platform();\n  const arch = os.arch();\n\n  const platformMapping = PLATFORM_MAPPINGS[platform];\n  if (!platformMapping) {\n    throw new Error(`Unsupported platform: ${platform}`);\n  }\n\n  const binaryName = platformMapping[arch] || PLATFORM_FALLBACK[platform];\n  return `${GITHUB_BASE_URL}/${binaryName}`;\n}\n\n// Download state — shared so status API can read it\nconst dlState = { downloading: false, progress: 0 };\n\nexport function getDownloadStatus() {\n  return { downloading: dlState.downloading, progress: dlState.progress };\n}\n\nfunction downloadFile(url, dest) {\n  return new Promise((resolve, reject) => {\n    const file = fs.createWriteStream(dest);\n\n    https.get(url, (response) => {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/tunnel/cloudflare/cloudflared.js#L31-L67","documentation":"getDownloadUrl() maps the current OS (via os.platform()) to a cloudflared binary name in PLATFORM_MAPPINGS to build a GitHub download URL. If os.platform() returns an OS with no entry in the mapping (anything beyond the supported darwin/linux/win32 set), it throws 'Unsupported platform: <platform>'. This is a hard fail-fast so the tunnel never attempts to download/run a nonexistent binary.","triggerScenarios":"Calling enableTunnel() (which resolves the cloudflared download URL) on an OS whose process.platform is not one of the mapped keys, e.g. freebsd, openbsd, aix, or sunos. Also occurs in exotic environments like FreeBSD jails, Android/Termux (platform 'android'), or alpine musl builds if the mapping only lists 'linux' variants separately.","commonSituations":"Running the 9Router gateway on a NAS/BSD-based home server, in a Termux environment on Android, on an unsupported CI runner OS, or after a Node/OS change where the platform string differs from what the mapping table covers.","solutions":["Run the gateway on a supported platform (darwin, linux, or win32).","Manually install cloudflared and place the binary where the tunnel code expects it so download is skipped.","Extend PLATFORM_MAPPINGS / PLATFORM_FALLBACK in src/lib/tunnel/cloudflare/cloudflared.js to cover your platform.","Check `node -e \"console.log(process.platform)\"` to confirm what string your environment reports and verify it against the mapping."],"exampleFix":"// before\nconst platformMapping = PLATFORM_MAPPINGS[platform];\nif (!platformMapping) {\n  throw new Error(`Unsupported platform: ${platform}`);\n}\n// after\nconst platformMapping = PLATFORM_MAPPINGS[platform] || PLATFORM_FALLBACK[platform];\nif (!platformMapping) {\n  throw new Error(`Unsupported platform: ${platform}`);\n}","handlingStrategy":"validation","validationCode":"import os from \"os\";\nconst SUPPORTED = [\"darwin\", \"linux\", \"win32\"];\nif (!SUPPORTED.includes(os.platform())) {\n  throw new Error(`Tunnel unsupported on this OS: ${os.platform()}`);\n}","typeGuard":"const isSupportedPlatform = (p) => typeof p === \"string\" && [\"darwin\",\"linux\",\"win32\"].includes(p);","tryCatchPattern":"try {\n  await enableTunnel(port);\n} catch (e) {\n  if (e.message.startsWith(\"Unsupported platform:\")) {\n    console.warn(\"Tunnel disabled: platform not supported\");\n    return;\n  }\n  throw e;\n}","preventionTips":["Gate tunnel features behind a platform check at app startup.","Use process.platform in feature flags so UI hides tunnel toggles on unsupported OSes.","Add tests asserting PLATFORM_MAPPINGS covers all values in a supported-platform list.","If you must support BSD/Android, extend the mapping and verify the binary URL exists."],"tags":["platform","cloudflare","tunnel","environment"],"backgroundTag":"unsupported-platform","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}