{"record":{"id":"e6f1aaa5fb043fea","repo":"wailsapp/wails","slug":"await-resp-text-e6f1aa","errorCode":null,"errorMessage":"${await resp.text()}","messagePattern":"\\$\\{await resp\\.text\\(\\)\\}","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/internal/runtime/desktop/@wailsio/runtime/src/stream.ts","lineNumber":699,"sourceCode":"// leaves the request slot free, which is what stops a backed-up connection from\n// starving the window's poll.\nasync function postWithRetry(headers: Record<string, string>, body: Uint8Array, signal?: AbortSignal): Promise<void> {\n    // Never retry with zero delay. The receiver being behind is a condition\n    // that takes time to clear, and an immediate retry is a busy loop of\n    // fetches — each one a scheme-handler round trip, and on the host a cgo\n    // call. Start at 1 ms and ramp.\n    let wait = 1;\n    for (;;) {\n        if (signal?.aborted) throw new StreamRequestCancelled();\n        const resp = await fetch(streamURL(\"send\"), {\n            method: \"POST\",\n            headers,\n            body: body as BodyInit,\n            signal,\n        });\n        if (resp.ok) return;\n        if (resp.status !== 429) {\n            throw new Error(await resp.text());\n        }\n        await sleep(wait, signal);\n        wait = Math.min(wait * 2, 50);\n    }\n}\n\n// postBatch sends several data frames for one connection in bounded requests.\n// Body: count u32, then count x ( len u32 | payload ). The combined body stays\n// within CHUNK_THRESHOLD: several individually small frames must not recreate\n// the WebView2 body-size problem that chunking single large frames avoids.\nasync function postBatch(connID: number, frames: Uint8Array[], signal?: AbortSignal): Promise<void> {\n    let start = 0;\n    while (start < frames.length) {\n        if (frames[start].byteLength > CHUNK_THRESHOLD) {\n            await postFrame(connID, KIND_DATA, frames[start], undefined, signal);\n            start++;\n            continue;\n        }","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/internal/runtime/desktop/@wailsio/runtime/src/stream.ts#L681-L717","documentation":"GlobalLock maps an HGLOBAL (allocated GMEM_MOVEABLE) into a pointer and increments its lock count; it returns NULL on failure. The w32 wrapper panics with 'GlobalLock failed' on NULL. Failure occurs when the handle is invalid/already freed, or when the block's lock count already exceeds its maximum — in practice an unbalanced lock/unlock loop, a freed handle, or locking memory that was allocated GMEM_FIXED (where lock semantics differ and NULL signals misuse on old code paths).","triggerScenarios":"Locking an HGLOBAL that was already GlobalFree'd; calling GlobalLock repeatedly in a retry loop without GlobalUnlock; locking a handle obtained from GetClipboardData after the clipboard has moved on and the handle is stale.","commonSituations":"Clipboard paste features: GetClipboardData → GlobalLock → process → forget GlobalUnlock; error branches that skip the unlock; holding the lock across OpenClipboard/CloseClipboard boundaries incorrectly.","solutions":["Pair every GlobalLock with a GlobalUnlock via defer, immediately after the lock succeeds.","Verify the handle is non-zero and currently owned by your code before locking.","For clipboard reads, keep the sequence tight: OpenClipboard, GetClipboardData, GlobalLock, copy out, GlobalUnlock, CloseClipboard.","Null-check the source of the handle (e.g. GetClipboardData can return 0) before attempting the lock."],"exampleFix":"// before\np := w32.GlobalLock(h)\nprocess(p)\nif err != nil { return } // GlobalUnlock never called\nw32.GlobalUnlock(h)\n\n// after\np := w32.GlobalLock(h)\nif p == nil { return errLockFailed }\ndefer w32.GlobalUnlock(h)\nprocess(p)\nreturn nil","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif msg, _ := r.(string); strings.HasPrefix(msg, \"GlobalLock failed\") {\n\t\t\tlog.Printf(\"clipboard lock failed: stale handle\")\n\t\t\treturn\n\t\t}\n\t\tpanic(r)\n\t}\n}()\np := w32.GlobalLock(h)","preventionTips":["Pair every GlobalLock with a deferred GlobalUnlock.","Null-check the handle source (GetClipboardData) before locking.","Keep clipboard read sequences tight: open, get, lock, copy, unlock, close."],"tags":["windows","memory","clipboard","syscall","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}