You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
web: Failed to send command over insecure HTTP origin (crypto.randomUUID is not a function) #55777
Web UI fails to send any command when accessed via insecure HTTP LAN IP with crypto.randomUUID is not a function. Blocks all prompting from that origin.
Environment
opencode version: v2.0.29
OS: Linux 6.1.42-antix.1-amd64-smp x86_64 (akms-RV409-RV509-RV709)
Thanks for the detailed report. I can reproduce this on v2.0.29, and it still happens on the latest dev (68510d9d6).
What I did: ran opencode serve --hostname 0.0.0.0, opened the web UI in Chromium through the machine's LAN IP (where isSecureContext is false and crypto.randomUUID is undefined), opened a session and submitted /btw what is 2+2. The toast "Failed to send command – crypto.randomUUID is not a function" appears right away and nothing is sent. The screenshots below show it on v2.0.29 and on dev, and the script below reproduces it.
The call that throws is in the /btw side-question command, which uses crypto.randomUUID() without checking that it exists. Because the error comes from a command, the toast says "command". I couldn't test a plain prompt here (no model credentials). If it also fails for you with ordinary text, not just a / command, please mention it. Until this is fixed, opening the UI via http://localhost (as you found) or over HTTPS avoids it.
Related: #46168 and #48144 are the same insecure-origin crypto.randomUUID problem in other parts of the web UI (session delete, file attach).
Reproduction script (repro.mjs)
// Repro for #55777: web UI over a non-localhost HTTP origin (insecure context, no crypto.randomUUID).// 1. cd <project> && opencode serve --hostname 0.0.0.0 --port 49374 (note the printed server password)// 2. ORIGIN=http://<lan-ip>:49374 PASSWORD=<pw> DIR=<project> CHROME=<chromium> node repro.mjs// Needs playwright-core (`npm i playwright-core`) and a Chromium binary (`npx playwright-core install chromium`).// <lan-ip> must be a non-localhost address so the page is not a secure context (crypto.randomUUID is undefined).import{chromium}from"playwright-core"const{ORIGIN,PASSWORD,DIR}=process.envconstauth="Basic "+Buffer.from(`opencode:${PASSWORD}`).toString("base64")constres=awaitfetch(`${ORIGIN}/api/session`,{method: "POST",headers: {authorization: auth,"content-type": "application/json","x-opencode-directory": DIR},body: JSON.stringify({title: "repro 55777"}),}).then((r)=>r.json())constid=res.data.idconstbrowser=awaitchromium.launch({executablePath: process.env.CHROME,args: ["--no-sandbox"]})constctx=awaitbrowser.newContext({httpCredentials: {username: "opencode",password: PASSWORD}})constpage=awaitctx.newPage()consterrors=[]page.on("pageerror",(e)=>errors.push("pageerror: "+e.message))page.on("console",(m)=>m.type()==="error"&&errors.push("console: "+m.text()))awaitpage.goto(ORIGIN,{waitUntil: "load"})console.log("isSecureContext:",awaitpage.evaluate(()=>isSecureContext),"typeof crypto.randomUUID:",awaitpage.evaluate(()=>typeofcrypto.randomUUID))awaitpage.waitForTimeout(3000)awaitpage.getByText("repro 55777").first().click()awaitpage.waitForTimeout(3000)consteditor=page.locator('[contenteditable="true"]').first()awaiteditor.click()awaitpage.keyboard.type("/btw what is 2+2",{delay: 20})awaitpage.waitForTimeout(500)awaitpage.keyboard.press("Escape")// close the slash popover if openawaitpage.keyboard.press("Enter")awaitpage.waitForTimeout(2500)awaitpage.screenshot({path: process.env.SHOT??"/workspace/repro/btw-insecure.png"})constbody=awaitpage.innerText("body")console.log("toast present:",/Failedtosendcommand/.test(body))console.log(body.split("\n").filter((l)=>/Failed|randomUUID/.test(l)).join("\n"))console.log(errors.join("\n"))awaitbrowser.close()
Verified independently on dev @ 775d1d0. Repro: serve the web UI over plain HTTP (LAN IP) so the context is insecure, submit any command → TypeError: crypto.randomUUID is not a function and the "Failed to send command" toast. Matches the bot's repro exactly.
Root cause is NOT in packages/app/src/runtime/persistence/uuid.ts (that one already has an insecure-context fallback). Tracing the toast through composer/submit.ts → command.trigger → the /btw client command lands in packages/gui-extensions/src/btw/model.ts: ask() calls crypto.randomUUID() directly. In insecure contexts crypto exists but randomUUID is undefined, so it throws before anything else runs.
I have a tested fix + regression test ready on a local branch:
const id = crypto.randomUUID?.() ?? Math.random().toString(16).slice(2) — mirrors the existing app-side fallback, no new strings.
New model.test.ts (2 tests): insecure-context test fails pre-fix with the exact TypeError, passes post-fix; secure-context control passes both ways. Post-fix: 2/2 green, typecheck (tsgo) clean, oxlint 0 errors.
One side note: model.ts statically imported @opencode/ui/toast (solid-sonner), which throws at import time in bun's test runtime and mock.module can't intercept the package specifier — so the toast UI is now lazy-imported in the empty-question branch only (per the repo's AGENTS.md dynamic-import pattern).
Requesting assignment per the contribution protocol — happy to open the PR when assigned.
Activity
opencode-agent commentedon Oct 15, 2026
Thanks for the detailed report. I can reproduce this on v2.0.29, and it still happens on the latest
dev(68510d9d6).What I did: ran
opencode serve --hostname 0.0.0.0, opened the web UI in Chromium through the machine's LAN IP (whereisSecureContextisfalseandcrypto.randomUUIDis undefined), opened a session and submitted/btw what is 2+2. The toast "Failed to send command – crypto.randomUUID is not a function" appears right away and nothing is sent. The screenshots below show it on v2.0.29 and ondev, and the script below reproduces it.The call that throws is in the
/btwside-question command, which usescrypto.randomUUID()without checking that it exists. Because the error comes from a command, the toast says "command". I couldn't test a plain prompt here (no model credentials). If it also fails for you with ordinary text, not just a/command, please mention it. Until this is fixed, opening the UI viahttp://localhost(as you found) or over HTTPS avoids it.Related: #46168 and #48144 are the same insecure-origin
crypto.randomUUIDproblem in other parts of the web UI (session delete, file attach).Reproduction script (repro.mjs)
Run it:
bun repro.mjsdrakeo338 commentedon Oct 15, 2026
I'm looking at this one and plan to open a fix shortly.
drakeo338 commentedon Oct 15, 2026
Releasing this one; I couldn't land a fix I'm confident in, so it's free for anyone else to take.
nosmile99 commentedon Oct 15, 2026
Verified independently on
dev@775d1d0. Repro: serve the web UI over plain HTTP (LAN IP) so the context is insecure, submit any command →TypeError: crypto.randomUUID is not a functionand the "Failed to send command" toast. Matches the bot's repro exactly.Root cause is NOT in
packages/app/src/runtime/persistence/uuid.ts(that one already has an insecure-context fallback). Tracing the toast throughcomposer/submit.ts→command.trigger→ the/btwclient command lands inpackages/gui-extensions/src/btw/model.ts:ask()callscrypto.randomUUID()directly. In insecure contextscryptoexists butrandomUUIDis undefined, so it throws before anything else runs.I have a tested fix + regression test ready on a local branch:
const id = crypto.randomUUID?.() ?? Math.random().toString(16).slice(2)— mirrors the existing app-side fallback, no new strings.model.test.ts(2 tests): insecure-context test fails pre-fix with the exact TypeError, passes post-fix; secure-context control passes both ways. Post-fix: 2/2 green,typecheck(tsgo) clean, oxlint 0 errors.model.tsstatically imported@opencode/ui/toast(solid-sonner), which throws at import time in bun's test runtime andmock.modulecan't intercept the package specifier — so the toast UI is now lazy-imported in the empty-question branch only (per the repo's AGENTS.md dynamic-import pattern).Requesting assignment per the contribution protocol — happy to open the PR when assigned.
Tarquinen commentedon Nov 2, 2026
Thanks for the report! This was fixed by #60462, which shipped in v2.2.3. Please upgrade, and open a new issue if it still happens.
— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊