AvaloniaUI/Avalonia · error · Error
Unable get Worker for pthread ${pthreadId}
Error message
Unable get Worker for pthread ${pthreadId} What it means
Thrown by WebRenderTargetRegistry.create when the located pthread object exposes neither a postMessage method nor a .worker property. The code needs a Worker reference to call transferControlToOffscreen and postMessage the canvas to the thread; without a worker handle the transfer is impossible.
Source
Thrown at src/Browser/Avalonia.Browser/webapp/modules/avalonia/rendering/webRenderTargetRegistry.ts:32
static create(pthreadId: number, canvas: HTMLCanvasElement, preferredModes: BrowserRenderingMode[]): number {
const id = WebRenderTargetRegistry.nextId++;
if (pthreadId === 0) {
WebRenderTargetRegistry.registry[id] = {
canvas
};
WebRenderTargetRegistry.targets[id] = WebRenderTargetRegistry.createRenderTarget(canvas, preferredModes);
} else {
const self = globalThis as any;
const module = self.Module ?? self.getDotnetRuntime(0)?.Module;
const pthreads = module?.PThread;
if (pthreads == null) { throw new Error("Unable to access emscripten PThread api"); }
const pthread = pthreads.pthreads[pthreadId];
if (pthread == null) { throw new Error(`Unable get pthread with id ${pthreadId}`); }
let worker: Worker | undefined;
if (pthread.postMessage != null) { worker = pthread as Worker; } else { worker = pthread.worker; }
if (worker == null) { throw new Error(`Unable get Worker for pthread ${pthreadId}`); }
const offscreen = canvas.transferControlToOffscreen();
worker.postMessage({
avaloniaCmd: "registerCanvas",
canvas: offscreen,
modes: preferredModes,
id
}, [offscreen]);
WebRenderTargetRegistry.registry[id] = {
canvas,
worker
};
}
return id;
}
static initializeWorker() {
const oldHandler = self.onmessage;
self.onmessage = ev => {View on GitHub (pinned to 11c5427268)
Solutions
- Verify the Emscripten version matches what the interop code expects for the pthread.worker field.
- Defer registration until the pthread worker is fully attached.
- Fall back to main-thread (pthreadId === 0) rendering if no worker handle can be obtained.
- Inspect the pthread object keys in the console to find the correct worker accessor.
Example fix
// before
if (pthread.postMessage != null) { worker = pthread as Worker; } else { worker = pthread.worker; }
if (worker == null) throw new Error(`Unable get Worker for pthread ${pthreadId}`);
// after
const worker = pthread.postMessage ? pthread : pthread.worker ?? pthread._worker;
if (!worker) { /* fall back to main-thread rendering */ return WebRenderTargetRegistry.create(0, canvas, modes); } Defensive patterns
Strategy: fallback
Validate before calling
const pthread = pthreads.pthreads[pthreadId];
const worker = pthread?.postMessage ? pthread : pthread?.worker;
if (!worker) { /* fall back to main-thread rendering (pthreadId 0) */ } Type guard
function hasWorkerHandle(pthreadId: number): boolean {
const self = globalThis as any;
const pthreads = (self.Module ?? self.getDotnetRuntime?.(0)?.Module)?.PThread?.pthreads;
const p = pthreads?.[pthreadId];
return !!(p && (p.postMessage || p.worker));
} Try / catch
try { return WebRenderTargetRegistry.create(pthreadId, canvas, modes); }
catch (e) {
if (e instanceof Error && /Worker for pthread/.test(e.message)) { return WebRenderTargetRegistry.create(0, canvas, modes); }
throw e;
} Prevention
- Verify the Emscripten version exposes pthread.worker (or pthread._worker).
- Defer registration until the pthread worker is attached.
- Keep a main-thread fallback when no worker handle is obtainable.
When it happens
Trigger: pthread.postMessage is null and pthread.worker is also null/undefined. Can happen with an unexpected Emscripten PThread object shape, a partially-initialized pthread, or a version mismatch between the interop assumptions and the actual Emscripten runtime internals.
Common situations: Emscripten version change altering the pthread object shape; a pthread in a transitional state (allocated struct but worker not yet attached); custom/patched runtime where the worker field has a different name.
Related errors
- Unable to access emscripten PThread api
- Unable get pthread with id ${pthreadId}
- Module.GL object wasn't initialized, WebGL can't be used.
- Unable to access .NET memory
- HTMLCanvasElement.getContext returned null.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/caa10ef44bf7ca21.
Report an issue: GitHub.