AvaloniaUI/Avalonia · error · Error
Unable get pthread with id ${pthreadId}
Error message
Unable get pthread with id ${pthreadId} What it means
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.
Source
Thrown at src/Browser/Avalonia.Browser/webapp/modules/avalonia/rendering/webRenderTargetRegistry.ts:28
worker?: Worker;
}); } = {};
private static nextId = 1;
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;
}View on GitHub (pinned to 11c5427268)
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.
Example fix
// before
const pthread = pthreads.pthreads[pthreadId];
if (pthread == null) throw new Error(`Unable get pthread with id ${pthreadId}`);
// after
let pthread = pthreads.pthreads[pthreadId];
if (!pthread && pthreads.currentWorkers?.includes(pthreadId)) { /* wait/retry */ }
if (!pthread) throw new Error(`Unable get pthread with id ${pthreadId} (known: ${Object.keys(pthreads.pthreads).join(',')})`); Defensive patterns
Strategy: validation
Validate before calling
const self = globalThis as any;
const pthreads = (self.Module ?? self.getDotnetRuntime?.(0)?.Module)?.PThread?.pthreads;
if (!pthreads || !(pthreadId in pthreads)) { /* thread not live: wait or cancel */ } Type guard
function isPThreadLive(pthreadId: number): boolean {
const self = globalThis as any;
const pthreads = (self.Module ?? self.getDotnetRuntime?.(0)?.Module)?.PThread?.pthreads;
return !!pthreads && pthreadId in pthreads;
} Try / catch
try { return WebRenderTargetRegistry.create(pthreadId, canvas, modes); }
catch (e) {
if (e instanceof Error && /get pthread/.test(e.message)) { /* retry after thread creation completes */ }
throw e;
} Prevention
- Confirm the pthread is alive before registering a canvas to it.
- Cancel pending registrations when a thread exits.
- Avoid reusing freed pthread ids.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unable to access emscripten PThread api
- Unable get Worker for pthread ${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/92def1729297dce2.
Report an issue: GitHub.