{"record":{"id":"92def1729297dce2","repo":"AvaloniaUI/Avalonia","slug":"unable-get-pthread-with-id-pthreadid","errorCode":null,"errorMessage":"Unable get pthread with id ${pthreadId}","messagePattern":"Unable get pthread with id (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Browser/Avalonia.Browser/webapp/modules/avalonia/rendering/webRenderTargetRegistry.ts","lineNumber":28,"sourceCode":"        worker?: Worker;\n    }); } = {};\n\n    private static nextId = 1;\n\n    static create(pthreadId: number, canvas: HTMLCanvasElement, preferredModes: BrowserRenderingMode[]): number {\n        const id = WebRenderTargetRegistry.nextId++;\n        if (pthreadId === 0) {\n            WebRenderTargetRegistry.registry[id] = {\n                canvas\n            };\n            WebRenderTargetRegistry.targets[id] = WebRenderTargetRegistry.createRenderTarget(canvas, preferredModes);\n        } else {\n            const self = globalThis as any;\n            const module = self.Module ?? self.getDotnetRuntime(0)?.Module;\n            const pthreads = module?.PThread;\n            if (pthreads == null) { throw new Error(\"Unable to access emscripten PThread api\"); }\n            const pthread = pthreads.pthreads[pthreadId];\n            if (pthread == null) { throw new Error(`Unable get pthread with id ${pthreadId}`); }\n            let worker: Worker | undefined;\n            if (pthread.postMessage != null) { worker = pthread as Worker; } else { worker = pthread.worker; }\n\n            if (worker == null) { throw new Error(`Unable get Worker for pthread ${pthreadId}`); }\n            const offscreen = canvas.transferControlToOffscreen();\n            worker.postMessage({\n                avaloniaCmd: \"registerCanvas\",\n                canvas: offscreen,\n                modes: preferredModes,\n                id\n            }, [offscreen]);\n            WebRenderTargetRegistry.registry[id] = {\n                canvas,\n                worker\n            };\n        }\n        return id;\n    }","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Browser/Avalonia.Browser/webapp/modules/avalonia/rendering/webRenderTargetRegistry.ts#L10-L46","documentation":"Thrown by WebRenderTargetRegistry.create when the requested pthreadId is not present in Module.PThread.pthreads map. The pthread was never spawned, has already exited, or the id does not correspond to a live worker thread in the Emscripten runtime.","triggerScenarios":"WebRenderTargetRegistry.create(pthreadId, ...) with pthreadId != 0 where pthreads[pthreadId] is null/undefined. The worker thread died before the canvas registration, the id is stale, or pthreads were not yet registered for that id.","commonSituations":"A .NET thread that terminated before the browser tried to attach a canvas to it; a race where canvas registration races thread creation; passing a freed/recycled pthread id; timing issues during rapid thread create/destroy.","solutions":["Register the canvas only after confirming the pthread is alive in Module.PThread.pthreads.","Retry registration after a short delay if the pthread is mid-creation.","Handle thread exit/dispose to cancel pending canvas registrations for that pthreadId.","Log the available pthreads map keys to detect stale or wrong ids."],"exampleFix":"// before\nconst pthread = pthreads.pthreads[pthreadId];\nif (pthread == null) throw new Error(`Unable get pthread with id ${pthreadId}`);\n\n// after\nlet pthread = pthreads.pthreads[pthreadId];\nif (!pthread && pthreads.currentWorkers?.includes(pthreadId)) { /* wait/retry */ }\nif (!pthread) throw new Error(`Unable get pthread with id ${pthreadId} (known: ${Object.keys(pthreads.pthreads).join(',')})`);","handlingStrategy":"validation","validationCode":"const self = globalThis as any;\nconst pthreads = (self.Module ?? self.getDotnetRuntime?.(0)?.Module)?.PThread?.pthreads;\nif (!pthreads || !(pthreadId in pthreads)) { /* thread not live: wait or cancel */ }","typeGuard":"function isPThreadLive(pthreadId: number): boolean {\n  const self = globalThis as any;\n  const pthreads = (self.Module ?? self.getDotnetRuntime?.(0)?.Module)?.PThread?.pthreads;\n  return !!pthreads && pthreadId in pthreads;\n}","tryCatchPattern":"try { return WebRenderTargetRegistry.create(pthreadId, canvas, modes); }\ncatch (e) {\n  if (e instanceof Error && /get pthread/.test(e.message)) { /* retry after thread creation completes */ }\n  throw e;\n}","preventionTips":["Confirm the pthread is alive before registering a canvas to it.","Cancel pending registrations when a thread exits.","Avoid reusing freed pthread ids."],"tags":["browser","rendering","emscripten","pthread","worker","typescript"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}