Install
$ agentstack add skill-impertio-studio-cesiumjs-claude-skill-package-cesium-core-memory ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
CesiumJS Memory
Overview
CesiumJS holds GPU resources (textures, buffers, shaders, a WebGL context) that the JavaScript garbage collector cannot reclaim. Dropping a reference to a Viewer, Cesium3DTileset, Primitive, or DataSource does NOT free its GPU memory. Every such object exposes an explicit destroy() that must be called.
This skill covers four failure modes:
- GPU memory leaks from skipped
destroy()calls. - The roughly 16 WebGL contexts per browser tab limit.
- WebGL context loss and recovery.
- Distinguishing a real CesiumJS leak from a retained JavaScript reference.
Verified signatures are in references/methods.md. Runnable teardown code is in references/examples.md. Failure modes are in references/anti-patterns.md.
Core Rules
- ALWAYS call
destroy()on aViewer,Cesium3DTileset,Primitive, or
DataSource before dropping the last reference to it. GPU resources are NOT garbage-collected.
- After
destroy(), NEVER call any method exceptisDestroyed(). Any other
call throws DeveloperError. ALWAYS reassign the reference to undefined.
- NEVER destroy the same object twice. One owner destroys each object exactly
once. NEVER wrap destroy() in a try/catch to swallow a double-destroy error; fix the ownership instead.
- ALWAYS reuse one
Vieweracross views. NEVER construct a freshVieweron
every route change or component remount without destroying the previous one.
viewer.dataSources.remove(ds)does NOT destroy the data source: the
destroy parameter defaults to false. ALWAYS pass true to free it.
scene.primitives.remove(primitive)DOES destroy the primitive by default
(destroyPrimitives is true). NEVER also call primitive.destroy() after.
- ALWAYS remove every event listener (DOM and CesiumJS
Event) you added
before destroying the Viewer. A retained listener keeps the whole graph alive.
Quick Reference
| Object | Free it with | Notes | |--------|--------------|-------| | Viewer / CesiumWidget | viewer.destroy() | Call before removing the container from the DOM | | Cesium3DTileset | scene.primitives.remove(tileset) | destroyPrimitives true destroys it; do not double-destroy | | Primitive | scene.primitives.remove(primitive) | Same as above | | DataSource | viewer.dataSources.remove(ds, true) | The true is required; default is false | | All data sources | viewer.dataSources.removeAll(true) | The true is required | | Tileset GPU budget | tileset.cacheBytes | Default 536870912 bytes (512 MiB) | | Tileset overflow budget | tileset.maximumCacheOverflowBytes | Default 536870912 bytes (512 MiB) | | Render-loop errors | scene.renderError event | See context loss below | | Check destroyed state | object.isDestroyed() | The only safe call after destroy() |
Teardown Ordering
digraph teardown {
"Tearing down the whole app or unmounting the map?" [shape=diamond];
"Removing one object mid-session?" [shape=diamond];
"Call viewer.destroy() once" [shape=box];
"Use the owning collection's remove()" [shape=box];
"Reassign every reference to undefined" [shape=box];
"Tearing down the whole app or unmounting the map?" -> "Call viewer.destroy() once" [label="whole app"];
"Tearing down the whole app or unmounting the map?" -> "Removing one object mid-session?" [label="just one object"];
"Removing one object mid-session?" -> "Use the owning collection's remove()" [label="yes"];
"Call viewer.destroy() once" -> "Reassign every reference to undefined";
"Use the owning collection's remove()" -> "Reassign every reference to undefined";
}
Rule: there is exactly one owner per object. viewer.destroy() tears down the Scene and its primitive collections, so a tileset that lives in scene.primitives is freed by viewer.destroy(). NEVER also call tileset.destroy() in that case. For mid-session removal, let the owning collection do the destroy.
Correct full-teardown sequence:
- Remove every DOM and CesiumJS
Eventlistener you added. - Destroy any
ScreenSpaceEventHandleryou constructed yourself. - Call
viewer.destroy()once. - Reassign
viewerand every cached tileset/primitive/handler toundefined.
Destroy Patterns
// Full teardown of a Viewer.
function teardown(viewer) {
if (viewer && !viewer.isDestroyed()) {
viewer.destroy();
}
return undefined; // assign the return value back to the variable
}
viewer = teardown(viewer);
// Remove a tileset mid-session. The collection destroys it.
const removed = scene.primitives.remove(tileset);
tileset = undefined; // do NOT call tileset.destroy() afterwards
// Remove a data source mid-session. The `true` is mandatory.
viewer.dataSources.remove(dataSource, true);
dataSource = undefined;
The isDestroyed() guard before destroy() is correct and is not a fallback: it prevents a double-destroy DeveloperError when teardown can be reached by more than one code path (for example a React unmount plus an explicit close button). It does NOT mask a bug; double-destroy is a real ownership question.
Tileset GPU Budget
A Cesium3DTileset caches tile content in GPU memory. Two properties bound it:
cacheBytes: the GPU memory budget for cached tiles. Default536870912
bytes (512 MiB).
maximumCacheOverflowBytes: extra memory allowed beyondcacheByteswhen
the current view needs it. Default 536870912 bytes (512 MiB).
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188, {
cacheBytes: 256 * 1024 * 1024, // 256 MiB on a constrained device
maximumCacheOverflowBytes: 128 * 1024 * 1024,
});
ALWAYS lower cacheBytes for memory-constrained devices (mobile, embedded kiosks). The legacy property maximumMemoryUsage was deprecated in 1.107 and removed in 1.110. NEVER emit maximumMemoryUsage; it does not exist in 1.124+.
The WebGL Context Budget
Browsers cap the number of live WebGL contexts per tab at roughly 16. Each Viewer and CesiumWidget owns exactly one context. viewer.destroy() does not always release the context immediately (CesiumGS/cesium issue #11533), so rapid create/destroy cycles exhaust the budget.
- ALWAYS reuse a single long-lived
Viewer. Swap data sources and tilesets
in and out instead of rebuilding the Viewer.
- NEVER mount a new
Viewerper route or per component render without
destroying the previous one first.
- Symptom of exhaustion: a console warning about too many active WebGL
contexts, and a newly created Viewer renders a blank canvas.
WebGL Context Loss
A WebGL context can be lost when the GPU is under memory pressure (the CONTEXT_LOST_WEBGL condition). Handle it on two surfaces:
// 1. The standard DOM event on the canvas.
viewer.canvas.addEventListener("webglcontextlost", (event) => {
event.preventDefault(); // required to allow a later restore
}, false);
// 2. The CesiumJS render-loop error event.
viewer.scene.renderError.addEventListener((scene, error) => {
console.error("Render error:", error);
});
scene.renderError fires when an error is thrown inside render. The handler receives the Scene and the error. scene.rethrowRenderErrors controls what happens next: when false (default behavior) render returns normally after raising the event; when true the error is rethrown after the event. Keep it false in production so one bad frame does not kill the render loop.
CesiumJS does not provide rich automatic context-loss recovery. A reliable recovery is a full teardown of the Viewer followed by reconstruction.
Real Leak Versus Lost Reference
CesiumJS pools and reuses memory, so the JavaScript heap not shrinking right after a remove() is NOT proof of a leak. Confirm before chasing one:
- Run a complete create-use-destroy cycle, then force GC in DevTools.
- Take heap snapshots before the cycle and after GC; compare retained size.
- If a destroyed
Viewer, tileset, or your own objects are still retained,
inspect the retainer chain.
The most common cause of an apparent leak is a retained JavaScript reference, not a CesiumJS bug: a closure capturing the Viewer, an array still holding removed entities, or an event listener that was never removed. Verified leak patterns and their fixes are in references/anti-patterns.md.
Common Mistakes
| Mistake | Symptom | Fix | |---------|---------|-----| | Dropping a Viewer reference without destroy() | Heap and GPU memory climb | viewer.destroy() first | | New Viewer per route, old one kept | Blank canvas after ~16 navigations | Reuse one Viewer | | dataSources.remove(ds) without true | Data source memory never freed | Pass destroy as true | | primitive.destroy() after primitives.remove() | DeveloperError thrown | Remove OR destroy, not both | | Using an object after destroy() | DeveloperError thrown | Reassign to undefined | | Event listeners never removed | Whole graph stays alive | Remove every listener before teardown | | maximumMemoryUsage set | No effect; property removed | Use cacheBytes |
Reference Files
references/methods.md: verified signatures fordestroy/isDestroyed,
the collection remove methods, tileset budget properties, and the context loss API.
references/examples.md: complete teardown sequences, a React unmount
pattern, and a context loss handler.
references/anti-patterns.md: every leak and crash mode with root cause
and fix.
Related Skills
cesium-core-architecture: theViewer/Scene/Globehierarchy.cesium-core-performance:requestRenderModeand tileset LOD tuning.cesium-errors-memory: deeper debugging of leaks and context budget
exhaustion.
cesium-errors-rendering: blank globe and context loss diagnosis.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Impertio-Studio
- Source: Impertio-Studio/CesiumJS-Claude-Skill-Package
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.