Skip to content

Troubleshooting

Jangmyun edited this page Aug 1, 2026 · 1 revision

Troubleshooting

A checklist for the failures people actually hit, grouped by symptom. Open the browser devtools console first — copcesium logs node-level failures there rather than throwing (a single bad node shouldn't kill the stream).

Nothing renders at all

CORS errors in the console

Access to fetch … has been blocked by CORS policy

The .copc.laz file is cross-origin and the host isn't sending CORS headers. The server must send Access-Control-Allow-Origin permitting your app's origin (and allow the Range request header). On S3 this is a bucket CORS policy; on nginx an add_header Access-Control-Allow-Origin block. Same-origin hosting avoids this entirely.

Range Requests not supported

The whole file downloads, or you see 200 OK instead of 206 Partial Content in the Network tab.

copcesium fetches byte ranges, not whole files. The host must support Range headers and answer 206 Partial Content. S3, most CDNs, and static hosts do this by default; some app servers and proxies strip it. Check with:

curl -I -H "Range: bytes=0-100" https://your-host/file.copc.laz

You want HTTP/… 206 and an Accept-Ranges: bytes header back.

The camera never moved to the data

If autoFrame is false, load() won't fly to the dataset — you're looking at empty globe elsewhere. Either set autoFrame: true (default) or call dataSource.zoomTo() yourself.

Not actually a COPC file

Plain LAS/LAZ has no octree index and won't stream. Verify with pdal info file --metadata and look for copc: true. See Converting to COPC.

Cloud renders but in the wrong place

Wrong country / offset horizontally

The horizontal CRS was misdetected or missing from the file's WKT. Check the file's WKT (pdal info --metadata); if it's absent or an odd dialect, override explicitly:

{ proj: 'EPSG:XXXX', projDef: '+proj=…' }

See Coordinate Systems for how detection works and where to get proj4 strings.

Floating in the air or buried underground

Two common causes:

  • Feet not scaled to meterszFactor wasn't detected. Pass it explicitly (zFactor: 0.3048 for international feet, 0.30480061 for US survey feet).
  • Orthometric vs. ellipsoidal height mismatch — the data uses a geoid-based vertical datum. Apply a constant geoidOffset (meters) to line it up with the terrain.

A tiny dot or an absurdly huge blob

xyFactor is wrong — almost always a feet-based CRS that wasn't detected, so bounding spheres are mis-sized. Pass xyFactor explicitly (same value as the linear unit, e.g. 0.3048).

Console: "proj4 transform produced a non-finite coordinate"

proj4 returned Infinity/NaN for a point outside the projection's valid domain — the source CRS is wrong for this data. Re-check proj/projDef against what the file actually is.

Performance problems

Stuttering / slow to refine while flying

  • Lower maxVisibleNodes and/or raise sseThreshold to cut per-pass work.
  • Raise debounceMs (e.g. 200) so fast fly-throughs don't trigger constant re-selection.
  • Lower concurrency if the machine is CPU-bound on decode.

High memory use

  • Lower maxCacheNodes — the LRU cap. It's the main memory lever.
  • Lower maxVisibleNodes to cap what's on screen at once.
  • See the presets in Options & Tuning.

Re-fetches everything when I zoom back out

Raise maxCacheNodes so nodes you backtrack over stay cached instead of being evicted and re-decoded.

Bundler / build issues

Worker or WASM 404 in a consuming app

This should not happen — copcesium inlines the Worker and its laz-perf WASM into the single published .mjs at build time precisely to avoid it. If you see a 404 for a worker chunk or .wasm, you're likely importing from source (src/) rather than the built package, or a bundler is rewriting the inlined asset. Import from the package entry (copcesium), not a deep path.

"require is not defined" / CommonJS import fails

copcesium is ESM-only — there is no CommonJS build, because constructing the inlined Worker needs import.meta.url semantics that require() can't provide. Use import, and ensure your bundler/Node treats the package as ESM.

Cesium version conflicts

cesium is a peer dependency (>=1.100.0) — copcesium uses whichever copy your app installs. If low-level GPU APIs behave oddly, confirm you have a single Cesium instance (not two copies from a dependency mismatch).

Still stuck?

Open an issue with the COPC URL (or its WKT), your CopcDataSource.load() options, and the console output: https://github.com/Jangmyun/copcesium/issues