siyuan-note/siyuan · error · Error
Unable to allocate graph rendering resource
Error message
Unable to allocate graph rendering resource
What it means
requireValue() is the null-guard wrapper around WebGL resource allocators (createProgram, createShader, createVertexArray, createBuffer, getUniformLocation). Any of them returning null trips 'Unable to allocate graph rendering resource'. WebGL functions return null when the context is lost, when the implementation refuses allocation, or when a uniform name does not exist in the program.
Source
Thrown at app/src/layout/dock/graph/webglRenderer.ts:508
const gl = this.gl;
const shader = this.requireValue(gl.createShader(type));
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const message = gl.getShaderInfoLog(shader) || "Unable to compile graph shader";
gl.deleteShader(shader);
throw new Error(message);
}
return shader;
}
private getUniform(program: WebGLProgram, name: string) {
return this.requireValue(this.gl.getUniformLocation(program, name));
}
private requireValue<T>(value: T | null): T {
if (value === null) {
throw new Error("Unable to allocate graph rendering resource");
}
return value;
}
}
View on GitHub (pinned to 251596fc0d)
Solutions
- Add a webglcontextlost handler that sets a 'lost' flag and short-circuits requireValue so the renderer stops allocating.
- Cross-check each getUniform name against the actual uniform declarations in the linked program (optimizer strips unused ones).
- Tear down and recreate the renderer on webglcontextrestored, re-allocating all programs/buffers.
- Reduce the number of simultaneously live WebGL contexts (one graph dock at a time).
Example fix
// before
private getUniform(program: WebGLProgram, name: string) {
return this.requireValue(this.gl.getUniformLocation(program, name));
}
// after (distinguish location-missing from real alloc failure)
private getUniform(program: WebGLProgram, name: string) {
const loc = this.gl.getUniformLocation(program, name);
if (!loc) throw new Error(`Uniform '${name}' not found in program (stripped by optimizer?)`);
return loc;
} Defensive patterns
Strategy: try-catch
Type guard
function isWebGLContextLost(gl: WebGL2RenderingContext): boolean {
return gl.isContextLost();
} Try / catch
canvas.addEventListener('webglcontextlost', (e) => { e.preventDefault(); renderer?.dispose(); });
try { renderer = new WebGLRenderer(canvas); }
catch (e) { showGraphFallback(); } Prevention
- Handle 'webglcontextlost' to stop allocations on a dead context.
- Cross-check getUniform names against the linked program; unused uniforms are stripped.
- Recreate the renderer on 'webglcontextrestored'.
- Limit the number of simultaneously live WebGL contexts.
When it happens
Trigger: The webgl2 context was lost (webglcontextlost event) but the renderer kept allocating; too many buffers/VAOs exhausted driver pools; getUniformLocation called for a uniform name that the GLSL optimizer stripped because it is unused.
Common situations: Tab backgrounded and the OS reclaimed the GPU context; user opened dozens of graph tabs exhausting the context pool; a uniform was renamed in GLSL but getUniform still queries the old name; driver crash mid-session.
Related errors
- WebGL2 is unavailable
- Unable to link graph shader
- Unable to compile graph shader
- Canvas 2D is unavailable
- Failed to save agent session
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/a30e0a95345d97b4.
Report an issue: GitHub.