Common Issues
WebGPU Not Supported Error
Symptom: Error screen showing “WebGPU not supported. Please upgrade your browser.” Cause: Browser doesn’t support WebGPU (required as of February 2026) Solution: Upgrade to a WebGPU-compatible browser: Supported Browsers:- Chrome 113+ (recommended)
- Edge 113+
- Safari 18+ (macOS Sonoma or later)
- Firefox Nightly (experimental)
- All shaders use Three.js Shading Language (TSL)
- TSL only compiles to WGSL (WebGPU Shading Language)
- No WebGL fallback possible without rewriting all shaders
- Procedural grass, terrain, particles all require WebGPU
- Commit: 3bc59db (February 26, 2026)
- File:
packages/shared/src/systems/client/ClientGraphics.ts - User-friendly error screen shows browser upgrade instructions
Characters Vanishing
Symptom: Characters disappear after page refresh Cause: Missing Privy credentials—each refresh creates a new anonymous identity Solution: Configure Privy authentication:Assets Not Loading
Symptom: 404 errors for models/avatars Cause: CDN container not running Solution:bun run dev which starts it automatically.
Database Schema Errors
Symptom: Errors about missing columns or tables Cause: Schema changed but migrations not run Solution:Manifest Validation Errors
Symptom: DataManager validation errors about invalid JSON in manifest files Cause: Invalid JSON syntax in manifest files (trailing commas, missing quotes, etc.) Solution: Recent commits fixed several manifest JSON errors. Update to latest code:- Trailing commas in JSON arrays/objects
- Missing quotes around property names
- Incorrect .gitignore negation for manifest files
- Fixed invalid manifest JSONs causing DataManager validation errors (commit aa1ea2d)
- Corrected .gitignore manifest negation to properly track manifest files (commit 1f4551c)
- All manifest files now tracked in git for CI test data availability (commit 2dddf28)
Port Conflicts
Symptom: “Port already in use” errors Solution: Kill processes on conflicting ports:Build Errors
Symptom: Compilation fails Solution: Clean rebuild:ESLint Crashes with ajv TypeError
Symptom: ESLint crashes withTypeError: Class extends value undefined is not a constructor or null related to ajv
Cause: Forcing ajv@8 on @eslint/eslintrc which requires ajv@6 for Draft-04 schema support
Solution: Update to latest code (commit b344d9e fixed this):
- Removed
ajv>=8.18.0override from root package.json - @eslint/eslintrc needs ajv@6 for JSON Schema Draft-04 support
- Forcing ajv@8 caused TypeError crash in ESLint initialization
- Security fix for ajv (GHSA-2g4f-4pwh-qvx6) applied only to packages that support ajv@8
Drizzle Migration Failures in CI
Symptom: Server migration code fails with “table already exists” errors in CI, or migration 0050 fails with “relation already exists” (42P07) on fresh databases Cause: Multiple issues with migration system:- Running
drizzle-kit pushseparately creates tables without populating migration journal - Migration 0050 duplicated CREATE TABLE statements from earlier migrations without IF NOT EXISTS guards
SKIP_MIGRATIONS=truedidn’t skip table validation, causing failures when schema created externally
- Commit eb8652a: CI now uses
drizzle-kit pushfor declarative schema creation - Commit 6a5f4ee:
SKIP_MIGRATIONS=truenow skips table validation AND migration recovery loop - Commit e4b6489: Migration 0050 fixed with IF NOT EXISTS guards for idempotency
- Server’s built-in migrations have FK ordering issues (migration 0050 references
arena_roundsfrom older migrations) drizzle-kit pushcreates schema declaratively without these problemsSKIP_MIGRATIONS=truetells server to skip ALL migration-related checks when schema is created externally
agent_duel_stats(from migration 0039)arena_fee_sharesarena_staking_pointswallet_links
Circular Dependency Build Errors
Symptom: TypeScript errors about missing types from@hyperscape/shared or @hyperscape/procgen
Cause: Circular dependencies between packages during clean builds
Solution: The build system handles this automatically with resilient patterns:
- procgen ↔ shared: Uses
tsc || echoto exit 0 even with circular dep errors - plugin-hyperscape ↔ shared: Uses
--skipLibCheckin declaration generation - Packages produce partial output sufficient for downstream consumers
PhysX Build Fails
Symptom: Errors during PhysX compilation Cause: PhysX WASM build requires emscripten Solution: PhysX is pre-built and committed. If you must rebuild:Tests Failing
Symptom: Tests timeout or fail unexpectedly Causes:- Server running during tests
- Stale test data
- Port conflicts
- CI environment variance (slower than local)
- Missing WebGPU mocks for Three.js WebGPU renderer
- Geometry validation: Increased to 120s for intensive procgen tests
- Benchmark thresholds: Relaxed for NPCTickProcessor to account for CI variance
- Vitest timeout: Global timeout increased to prevent flaky failures
- Performance tests: Adjusted heap growth and scaling thresholds for parallel test contention
Integration Tests Fail with “anvil: command not found”
Symptom: Integration tests fail because the anvil binary is missing Cause: Foundry toolchain not installed in CI environment Solution: Update to latest code (commit b344d9e fixed this):Test Suite Fails with WebGPU Errors
Symptom: Tests fail with “GPUShaderStage is not defined” or similar WebGPU errors Cause: Three.js WebGPU renderer expects browser globals that don’t exist in test environment Solution: Update to latest code (commit 25ba63c fixed this): Technical Details:- Added
vitest.setup.tsto mock WebGPU browser globals - Mocks: GPUShaderStage, GPUBufferUsage, GPUTextureUsage, etc.
- Required by Three.js WebGPU renderer in tests
- Fixed in
packages/server/vitest.setup.ts
ArenaService Tests Fail After Refactor
Symptom: ArenaService tests fail with “Cannot spy on private method” errors Cause: Refactored ArenaService architecture moved methods to sub-services Solution: Update to latest code (commit 25ba63c fixed this): Technical Details:- Added protected passthrough methods on ArenaService for test spying
- Methods: getDb, getEligibleAgents, findReferralMappingForWalletNetwork, etc.
- Database mock helper:
setDbMockproperly configures world.getSystem(“database”) mock - Some tests skipped pending deeper refactoring (85 skipped, 1569 passing)
WebSocket Connection Failed
Symptom: Can’t connect to game server Causes:- Server not running
- Wrong port configuration
- Firewall blocking
- Verify server is running:
lsof -i:5555 - Check client config:
PUBLIC_WS_URL - Ensure no firewall blocks
Hot Reload Not Working
Symptom: Changes don’t appear in browser Causes:- Build cache stale
- Wrong directory
Database Pool Starvation
Symptom: “200 pending operations” warnings, game freezes during batch operations (fletching, smithing) Cause: Concurrent inventory writes exhausting database connection pool Solution: Update to latest code (PR #823 fixed this). The system now uses write coalescing:- Write coalescing keeps only the latest inventory snapshot
- At most 2 transactions per player: one active + one queued
- All waiting callers resolve when batch completes
- Prevents PostgreSQL deadlocks and pool exhaustion
packages/server/src/systems/DatabaseSystem/index.ts for inventoryWriteActive and inventoryWriteQueued maps.
Camera Facing Backwards on Fresh Load
Symptom: Camera initializes in front of player, causing backwards movement controls Cause: Camera spherical coordinates initialized withtheta=0 instead of theta=Math.PI
Solution: Update to latest code (PR #829 fixed this)
Technical Details:
- Camera uses spherical coordinates (radius, phi, theta)
theta=0places camera in front of player (incorrect)theta=Math.PIplaces camera behind player (correct third-person view)- Fixed in
ClientCameraSystem.tsinitialization and reset methods
Entity Outlines Showing Wrong Colors
Symptom: Entity highlights show incorrect color grading when hovering, even with post-processing disabled Cause: Post-processing outline pass shares shader pipeline with LUT color grading, causing stale LUT data to leak into outline-only rendering Solution: Update to latest code (PR #829 fixed this) Technical Details:- LUT intensity now zeroed when color grading is disabled
- Rendering routes through composer even when post-processing is off
- Ensures entity highlights work correctly without color grading artifacts
- Fixed in
ClientGraphics.tsandPostProcessingFactory.ts
Remote Players Facing Sideways
Symptom: Other players appear to face sideways or show T-pose ghosts in multiplayer Cause: Missing quaternion sync and transform updates after async avatar loading Solution: Update to latest code (PR #875 fixed this) Technical Details:base.quaternionnow synced inPlayerRemotefor correct facing direction- Force transform update after async avatar load prevents T-pose ghosts
- Spatial index updated after teleport/respawn so
sendToNearbyreaches players at new location - Authoritative position broadcast to all players on join
- Fixed in
PlayerRemote.tsandServerNetwork/index.ts
Equipment Not Visible on Other Players
Symptom: Equipment doesn’t appear on remote players, or only shows after reconnect Cause: Equipment packets sent before VRM avatar loaded, or lost during disconnect Solution: Update to latest code (PR #875 fixed this) Technical Details:- Subscribe to
AVATAR_LOAD_COMPLETEto replay cached equipment when VRM loads - Re-send equipment on socket reconnect (recovers packets lost during disconnect)
- Send existing players’ equipment to joiner and broadcast joiner’s equipment
- Use all 11
EQUIPMENT_SLOT_NAMESinstead of hardcoded 6 slots - Fixed in
EquipmentVisualSystem.tsandServerNetwork/index.ts
Duel Loser Stuck in Arena
Symptom: After duel ends, loser is stuck in arena with frozen physics and cannot move or respawn Cause: Winner’s health restore exception prevented loser’s health restore from executing Solution: Update to latest code (PR #875 fixed this) Technical Details:- Split health restores into individual try/catch blocks
- Previously both
restorePlayerHealthcalls were in single try/catch - If winner’s restore triggered exception in any
PLAYER_RESPAWNEDhandler, loser’s restore was skipped - Left loser with frozen physics,
isDying=true, and noplayerRespawned/playerSetDeadpackets - Each restore now individually wrapped, matching teleport pattern
- Fixed in
DuelCombatResolver.ts
PvP Ranged Attacks Granting Wrong XP
Symptom: Killing players with ranged attacks in duels grants Strength XP instead of Ranged XP Cause: XP calculation used player’s melee attack style instead of actual weapon type Solution: Update to latest code (PR #875 fixed this) Technical Details:PlayerDeathSystemnow detects weapon type (bow/crossbow/staff) for PvP kills- Previously used player’s melee attack style, incorrectly granting Strength XP
- Now matches
MobEntitylogic: inspect actual weapon type for XP calculation - Fixed in
PlayerDeathSystem.ts
Logs
Server Logs
Check terminal output wherebun run dev is running.
Test Logs
Docker Logs
Database Prepared Statements Error (XX000)
Symptom: Database queries fail with error codeXX000 when using Supabase Supavisor pooler
Cause: Supavisor connection pooler doesn’t support prepared statements in transaction mode
Solution: Update to latest code (commits 8aaaf28, f7ab9f7 fixed this). Prepared statements are now disabled for Supavisor:
- Supavisor pooler operates in transaction mode
- Transaction mode doesn’t support prepared statements (PostgreSQL limitation)
- Disabling prepared statements trades minor performance for compatibility
- Only affects Supabase deployments using Supavisor pooler
- Local PostgreSQL and other providers unaffected
- Using Supabase with Supavisor pooler
- Getting XX000 errors on database queries
- Connection string contains
pooler.supabase.com
- Local PostgreSQL development
- Direct PostgreSQL connections (no pooler)
- PgBouncer in statement mode
- Neon, Railway, or other providers without transaction pooling
Streaming WebGPU Backend Issues (RTX 4090)
Symptom: WebGPU rendering fails or crashes on RTX 4090 GPUs in streaming mode Cause: ANGLE backend defaulting to GL instead of Vulkan for RTX 4090 Solution: Update to latest code (commit 80bb06ed fixed this). ANGLE now uses Vulkan backend for RTX 4090:- RTX 4090 requires Vulkan backend for optimal WebGPU performance
- GL backend causes rendering issues and crashes
- Automatically detected based on GPU model string
- Only affects streaming/headless mode with RTX 4090
- Fixed in
packages/server/src/streaming/browser-capture.ts
--use-angle=vulkan when RTX 4090 is detected.
Deployment Issues
Docker Build Failures
Symptom: Native module compilation fails in minimal Docker images Cause: Missing build tools in base image Solution: Ensurebuild-essential is installed:
- Added
build-essentialfor native module compilation (commit bd2aad9) - Added
git-lfsfor asset checks (commit 87b3c1a) - Added
unzipfor bun install (commit 18d6126)
DNS Resolution Failures
Symptom: Cannot resolve external domains in Docker containers Cause: Default DNS servers not working in container environment Solution: Overwriteresolv.conf with Google DNS:
- Changed from appending to overwriting
resolv.conf(commit fd17248)
Asset Download in Production
Symptom: Production builds try to download assets from Git LFS Cause: Asset download script runs in production environment Solution: SetCI=true to skip asset download:
- Added
CI=truecheck to skip asset download in production (commit 28bf9fb)
Streaming Dependencies Missing
Symptom: Streaming mode fails with missing Playwright or ffmpeg Cause: Playwright dependencies and ffmpeg not installed in deployment image Solution: Install required dependencies:- Added Playwright deps and ffmpeg for streaming (commit 5920467)
CORS Issues in Betting Service
Symptom: Preflight OPTIONS requests fail from betting frontend Cause: Missing CORS configuration or max-age header Solution: Configure CORS to allow all origins with max-age:- Allow all origins and add CORS max-age (commit 7256b07)
- Allow hyperscape-betting.pages.dev origin (commit fb3b9cd)
- Allow pointer events on stream-bg for Twitch embed interaction (commit 0925171)
Streaming Issues
Stream Not Appearing on Twitch/Kick/X
Symptom: FFmpeg running but stream not visible on platforms Cause: Incorrect stream keys or RTMP URLs Solution: Verify stream keys are configured correctly:- Stale stream keys in shell environment overriding .env file
- Missing
/apppath in Kick RTMP URL - Wrong RTMP URL format
- Fixed Kick RTMP URL from
ingest.kick.comto correct IVS endpoint (commit 5dbd239) - Added all stream keys to CI/CD secrets flow (commit 5dbd239)
- Fixed stream key environment variable handling in deploy scripts (commits 7ee730d, a71d4ba)
WebGPU Crashes on RTX 5060 Ti
Symptom: Chrome crashes or freezes when using WebGPU on RTX 5060 Ti GPUs Cause: Broken Vulkan ICD on RTX 5060 Ti Solution: Use GL ANGLE backend instead of Vulkan:- Removed RTX 5060 Ti from GPU search (commit 30cacb0)
- Switch to GL ANGLE backend for RTX 5060 Ti (commit 0257563)
- WebGPU-safe Chrome flags (removed aggressive GPU opts) (commit f3aa787)
FFmpeg SIGSEGV in Static Builds
Symptom: FFmpeg crashes with segmentation fault when using static builds Cause: Static FFmpeg builds incompatible with some system configurations Solution: Use system FFmpeg instead:- Use system FFmpeg to avoid static build SIGSEGV (commits 55a07bd, 536763d)
Streaming Black Screen
Symptom: Stream shows black screen instead of game Causes:- GPU not accessible in headless mode
- Wrong Chrome backend
- Missing Xvfb for headful mode
- Switch back to headful mode for GPU compositing with Xvfb (commit 5e4c6f1)
- Use swiftshader + headless + WebGL for stable streaming (commit ae42beb)
Chrome Dev Channel Not Found
Symptom: Cannot find Chrome Dev channel executable on Vast.ai Cause: Chrome Dev not installed or wrong path Solution: Install Chrome Dev channel:- Use Chrome Dev channel for WebGPU support on Vast.ai (commits ba8bd53, d824163)
Tauri Build Fails with Empty APPLE_CERTIFICATE
Symptom: Tauri macOS builds fail withSecKeychainItemImport error even when not doing a release build
Cause: Tauri bundler attempts code signing whenever APPLE_CERTIFICATE env var exists, even if empty
Solution: Update to latest code (commit 15250d2 fixed this)
Technical Details:
- Build workflow now split into Unsigned and Release variants
- Signing env vars only present during actual releases
- Non-release builds no longer set
APPLE_CERTIFICATE='' - macOS unsigned builds use
--no-bundleinstead of--bundles app(app bundle type is macOS-only) - iOS builds are release-only (unsigned iOS always fails with “Signing requires a development team”)
- Windows builds include retry logic for transient NPM registry errors
- File:
.github/workflows/build-app.yml - Commit: 15250d2 (Feb 25, 2026)
Linux/Windows Desktop Builds Fail in CI
Symptom: Tauri desktop builds fail on Linux/Windows with “app bundle type is macOS-only” error Cause:--bundles app flag is macOS-specific, causes Linux/Windows builds to fail
Solution: Update to latest code (commit f19a704 fixed this)
Technical Details:
- Replaced
--bundles appwith--no-bundlefor unsigned builds appbundle type is macOS-only, causing Linux/Windows to fail- Made
beforeBuildCommandcross-platform using Node.js instead of Unix shelltestcommand - Split artifact upload: release builds upload bundles, unsigned builds upload raw binaries
- File:
.github/workflows/build-app.yml - Commit: f19a704 (Feb 26, 2026)
Cloudflare Origin Lock Blocking API Access
Symptom: Frontend cannot access API directly, getting origin lock errors Cause: Cloudflare origin lock preventing direct frontend API access Solution: Update to latest code (commit 3ec9826 fixed this) Technical Details:- Disabled cloudflare origin lock in server configuration
- Allows direct API access from frontend
- File:
packages/server/(server configuration) - Commit: 3ec9826 (Feb 25, 2026)
Cloudflare Pages Worker Deployment Error
Symptom: Cloudflare Pages deployment fails with worker deployment error Cause: Missing build output directory specification in Cloudflare configuration Solution: Update to latest code (commit 1af02ce fixed this) Technical Details:- Specified pages build output dir in Cloudflare configuration
- Cloudflare Pages deployments now succeed
- Commit: 1af02ce (Feb 25, 2026)
Cloudflare Wrangler Configuration Issues
Symptom: Cloudflare Pages deployment fails with configuration errors or uses wrong directive Cause: Incorrect wrangler.toml configuration for Pages deployment Solution: Update to latest code (commit 42a1a0e fixed this) Technical Details:- Switched from
pages_build_output_dirto[assets]directive - Works better with
wrangler deployfor static asset hosting - Deploy command should be empty in Cloudflare dashboard
- File:
packages/client/wrangler.toml - Commit: 42a1a0e (Feb 26, 2026)
Root Wrangler Config Conflicts with Pages Project
Symptom: Cloudflare deployment confusion between Worker and Pages projects Cause: Rootwrangler.toml named “hyperscape-betting” conflicts with “hyperscape” Pages project
Solution: Update to latest code (commit f19a704 fixed this)
Technical Details:
- Removed root
wrangler.tomlto avoid deployment confusion - Correct Pages configuration is in
packages/client/wrangler.toml - To complete fix, update Cloudflare Dashboard:
- Workers & Pages → hyperscape (Worker) → Settings → disconnect GitHub
- Workers & Pages → hyperscape (Pages) → Settings → connect GitHub
- Commit: f19a704 (Feb 26, 2026)
Assets Not Found After Fresh Clone
Symptom: Server fails to start with “No world areas defined” or manifest validation errors Cause: Assets directory not cloned from HyperscapeAI/assets repository Solution: Assets are automatically cloned duringbun install. If missing:
- Assets are sourced from HyperscapeAI/assets repository
scripts/ensure-assets.mjsruns duringbun installpostinstall hook- Local dev: Full clone with LFS (~200MB)
- CI: Shallow clone without LFS (manifests only, ~1MB)
- Entire
packages/server/world/assets/directory is gitignored
Model Cache Issues
Symptom: Missing objects in models (e.g., altars), white/wrong colored textures after restart, or grey trees in WebGPU builds Cause: Bugs in IndexedDB processed model cache (fixed in PR #935, commit c98f1cc, Feb 25, 2026) Solution: Update to latest code. The cache now uses:- Object-identity mapping instead of name-based lookup (fixes missing objects)
- Raw RGBA pixel extraction for textures (fixes lost textures)
- Duck-type property checks for materials (fixes grey trees in WebGPU)
- Problem:
serializeNodeusedfindIndex-by-name to map hierarchy nodes to mesh data. Models with duplicate mesh names (common: "", “Cube”, “Cube”) all resolved to the same index. During deserialization, Three.jsadd()auto-removes from previous parent, so only the last reference survived. - Fix: Use
Map<Object3D, number>identity map built during traversal instead of name-based lookup - Impact: All objects in models now render correctly, including complex multi-mesh models like altars
- Problem: Textures were serialized as ephemeral
blob:URLs but never reloaded during deserialization. After page refresh, blob URLs became invalid, leaving models white or incorrectly colored. - Fix: Extract raw RGBA pixels via canvas
getImageData(synchronous) and restore asTHREE.DataTexture— no async loading race conditions - Impact: Textures persist correctly across page refreshes, models maintain correct colors
- Problem:
createDissolveMaterialusedinstanceof MeshStandardMaterialwhich fails forMeshStandardNodeMaterialin the WebGPU build where they are separate classes - Fix: Replaced with duck-type property check (
src.color && src.roughness !== undefined) - Impact: Tree materials render correctly in WebGPU builds instead of appearing grey
- Added
localStorage.setItem('disable-model-cache', 'true')to bypass cache for debugging - Error logging on IndexedDB
put/transaction failures - Cache version bumped to 3 to invalidate broken entries
- File:
packages/shared/src/utils/rendering/ModelCache.ts - PR: #935 | Commit: c98f1cc (Feb 25, 2026)
Terrain Height Offset Issues
Symptom: Players/entities positioned 50m above or below expected terrain height Cause: Tile index and grid index calculations didn’t account for PlaneGeometry’s centered coordinate system Solution: Update to latest code (commit 21e0860 fixed this) Technical Details:- Tile Index Bug:
Math.floor(worldX/TILE_SIZE)doesn’t account for centered geometry- PlaneGeometry uses [-50, +50] range, not [0, 100]
- Fixed with
worldToTerrainTileIndex()canonical helper
- Grid Index Bug: Formula omitted
halfSizeoffset from PlaneGeometry’s centered range- Fixed with
localToGridIndex()canonical helper - Applied to both
getHeightAtCached()andgetTerrainColorAt()
- Fixed with
- Key Format Bug:
getTerrainColorAt()had comma-vs-underscore typo preventing tile lookups- Changed from
${tileX},${tileZ}to${tileX}_${tileZ}
- Changed from
packages/shared/src/systems/shared/world/TerrainSystem.ts
Cyclic Dependency Build Errors
Symptom: TypeScript errors about missing types from@hyperscape/shared or @hyperscape/procgen, or Turbo detecting circular dependencies
Cause: Circular dependencies between packages during clean builds
Solution: Update to latest code (commits f355276, 3b9c0f2, 05c2892 fixed shared/procgen cycle). The build system handles this automatically with resilient patterns:
- procgen ↔ shared: Fully broken cycle via peerDependencies + devDependencies
- Commit f355276: Moved procgen from dependencies to optional peerDependencies in shared
- Commit 3b9c0f2: Removed cross-references entirely from both package.json files
- Commit 05c2892: Added procgen as devDependency in shared for TypeScript type resolution
- Turbo treats peerDependencies as graph edges, so peerDependencies alone was insufficient
- devDependencies are not followed by turbo’s
^buildtopological ordering (no cycle) - Imports still resolve at runtime via bun workspace resolution (both packages always installed together)
- plugin-hyperscape ↔ shared: Uses
--skipLibCheckin declaration generation - Packages produce partial output sufficient for downstream consumers
- Commit 05c2892 (Feb 26, 2026): Added procgen as devDependency for TypeScript type resolution
- Commit 3b9c0f2 (Feb 26, 2026): Fully broke shared↔procgen cycle by removing cross-references
- Commit f355276 (Feb 25, 2026): Initial fix moving procgen to peerDependencies
- Files:
packages/shared/package.json,packages/procgen/package.json
Shared/Procgen Type Resolution Issues
Symptom: TypeScript can’t find@hyperscape/procgen module declarations during type checking in shared package
Cause: procgen removed from dependencies to break circular dependency, but TypeScript still needs it for type resolution
Solution: Update to latest code (commit 05c2892 fixed this)
Technical Details:
- Added procgen as
devDependencyin shared’s package.json - devDependencies are not followed by turbo’s
^buildtopological ordering (doesn’t create cycle) - Ensures bun links the package so TypeScript can find module declarations during type checking
- Imports still resolve at runtime via bun workspace resolution
- File:
packages/shared/package.json - Commit: 05c2892 (Feb 26, 2026)
ESLint Crashes in Asset Forge
Symptom: ESLint crashes with errors aboutimport/order rule using removed sourceCode.getTokenOrCommentBefore API
Cause: eslint-plugin-import@2.32.0 is incompatible with ESLint 10 - uses removed API
Solution: Update to latest code (commits cadd3d5, b5c762c fixed this)
Technical Details:
- Disabled cascaded
import/orderrule in asset-forge’s flat config - Used
eslint srcinstead ofeslint . --ext .ts,.tsxto avoid linting entire directory - Prevents eslint-plugin-import’s import/order rule from crashing
- Files:
packages/asset-forge/eslint.config.mjs,packages/asset-forge/package.json - Commits: cadd3d5, b5c762c (Feb 26, 2026)
Cloudflare Pages Deploy Fails with Wrangler Config Error
Symptom: Cloudflare Pages deployment fails with configuration errors Cause: Incorrect wrangler.toml configuration for Pages deployment Solution: Update to latest code (commit 42a1a0e fixed this) Technical Details:- Switched from
pages_build_output_dirto[assets]directive - Works better with
wrangler deployfor static asset hosting - Deploy command should be empty in Cloudflare dashboard
- File:
packages/client/wrangler.toml - Commit: 42a1a0e (Feb 26, 2026)
Root Wrangler Config Conflicts with Pages Project
Symptom: Cloudflare deployment confusion between Worker and Pages projects Cause: Rootwrangler.toml named “hyperscape-betting” conflicts with “hyperscape” Pages project
Solution: Update to latest code (commit f19a704 fixed this)
Technical Details:
- Removed root
wrangler.tomlto avoid deployment confusion - Correct Pages configuration is in
packages/client/wrangler.toml - To complete fix, update Cloudflare Dashboard:
- Workers & Pages → hyperscape (Worker) → Settings → disconnect GitHub
- Workers & Pages → hyperscape (Pages) → Settings → connect GitHub
- Commit: f19a704 (Feb 26, 2026)
Linux/Windows Desktop Builds Fail in CI
Symptom: Tauri desktop builds fail on Linux/Windows with “app bundle type is macOS-only” error Cause:--bundles app flag is macOS-specific, causes Linux/Windows builds to fail
Solution: Update to latest code (commit f19a704 fixed this)
Technical Details:
- Replaced
--bundles appwith--no-bundlefor unsigned builds appbundle type is macOS-only, causing Linux/Windows to fail- Made
beforeBuildCommandcross-platform using Node.js instead of Unix shelltestcommand - Split artifact upload: release builds upload bundles, unsigned builds upload raw binaries
- File:
.github/workflows/build-app.yml - Commit: f19a704 (Feb 26, 2026)
Mage Agents Not Attacking in Duels
Symptom: Mage agents stand idle during duels, no spell projectiles visible Cause: Combat state key mismatch betweenCombatStateService and EmbeddedHyperscapeService
Solution: Update to latest code (PR #933 fixed this)
Technical Details:
CombatStateServicesyncs abbreviated keys (data.c/data.ct) for network efficiencyEmbeddedHyperscapeService.getGameState()only read full keys (data.inCombat/data.combatTarget)- DuelCombatAI always saw
inCombat=falseand floodedexecuteAttackevery tick - Fixed by reading both abbreviated and full keys:
- File:
packages/server/src/eliza/EmbeddedHyperscapeService.ts - Commit: 82ff784 (Feb 25, 2026)
Duplicate Magic Projectiles
Symptom: Magic attacks spawn two projectiles, runes consumed twice Cause: TOCTOU race condition inhandleMagicAttack cooldown claim
Solution: Update to latest code (PR #933 fixed this)
Technical Details:
- Cooldown was checked early but claimed after async
consumeRunesForSpellcall - With combat state bug flooding attacks, two concurrent invocations could both pass cooldown check
- Fixed by moving cooldown claim before async rune consumption:
- File:
packages/shared/src/systems/shared/combat/handlers/MagicAttackHandler.ts - Commit: 82ff784 (Feb 25, 2026)
Players Sinking Into Duel Arena Floors
Symptom: Players/agents appear to sink ~0.4m into duel arena floors, grass grows through floor surfaces Cause: Flat zones were removed from terrain system, causinggetHeightAt() to return raw procedural terrain height instead of floor-level height
Solution: Update to latest code (PR #911 fixed this)
Technical Details:
DuelArenaVisualsSystemnow registers flat zones programmatically for all 8 floor areas- Affected areas: 6 arenas (2×3 grid), lobby (60×30), hospital (20×15)
- Terrain height queries now return correct floor-level values
- Terrain mesh is carved under floors via flat zone registration
- File:
packages/shared/src/systems/client/DuelArenaVisualsSystem.ts - Commit: 7a60135 (Feb 25, 2026)
Cannot Click to Move in Duel Arenas
Symptom: Click targets go underground in duel arenas, players cannot move Cause: Building footprint validation rejecting arena-floor raycast hits Solution: Update to latest code (commit 2435423 fixed this) Technical Details:RaycastServicenow skips building footprint validation for arena-floor raycast hits- File:
packages/shared/src/systems/client/interaction/services/RaycastService.ts - Commit: 2435423 (Feb 24, 2026)
Duel Arena Minimap Shows Black Holes
Symptom: Minimap shows duel arenas as black holes, unusable in arena area Cause: Arena/lobby/hospital floor meshes had layer 0 disabled Solution: Update to latest code (commit 2435423 fixed this) Technical Details:- Enabled layer 0 on arena/lobby/hospital floor meshes so minimap camera can render them
- File:
packages/shared/src/systems/client/DuelArenaVisualsSystem.ts - Commit: 2435423 (Feb 24, 2026)
Victory Emote Overridden by Combat Cleanup
Symptom: Winning agent’s wave emote is immediately overwritten by idle animation after duel victory Cause: Combat animation system’s stale idle resets override victory emote Solution: Update to latest code (commit 645137386 fixed this) Technical Details:- Delayed Victory Emote: Victory emote now delayed by 600ms after combat resolution
- Allows all death/combat cleanup (emote resets, combat state teardown, scheduled animation resets) to finish first
- Without delay, victory emote was immediately overwritten by stale idle resets from combat animation system
- Emote Reset in stopCombat: Reset emote to idle when agents teleport out
- Ensures wave animation stops when agents leave arena
- Prevents emote from persisting after duel ends
- Entity Data Sync: Set emote on server entity so future entity sync includes it
- Ensures victory emote is part of entity state
- Broadcasts to all clients via
entityModifiedpacket
- File:
packages/server/src/systems/StreamingDuelScheduler/managers/DuelOrchestrator.ts - Commit: 645137386 (Feb 25, 2026)
WebSocket Type Errors
Symptom: TypeScript errors about missingremoveAllListeners and on methods on WebSocket connections
Cause: Fastify websocket connections use ws library type, not browser WebSocket
Solution: Update to latest code (commit efba5a0 fixed this)
Technical Details:
- Import proper WebSocket type from
wslibrary:import type { WebSocket } from 'ws' - Fastify’s
@fastify/websocketuses thewslibrary under the hood - Browser WebSocket type doesn’t have Node.js EventEmitter methods
- File:
packages/server/src/systems/ServerNetwork/index.ts - Commit: efba5a0 (Feb 26, 2026)
Asset-Forge TypeScript Strict Mode Errors
Symptom: TypeScript errors in asset-forge about implicitany types in traverse callbacks
Cause: TypeScript strict mode requires explicit types for callback parameters
Solution: Update to latest code (commits 82f97da, 42e52af fixed this)
Technical Details:
- Traverse Callbacks (commit 82f97da): Added type annotations for traverse callbacks
- Example:
(child: THREE.Object3D) => { ... }instead of(child) => { ... } - Required by TypeScript strict mode
- Example:
- Module Resolution (commit 42e52af): Updated to
moduleResolution: "bundler"- Three.js WebGPU subpath requires
bundlerornode16module resolution - Previous
'node'setting couldn’t resolve the exports map correctly - File:
packages/asset-forge/tsconfig.json
- Three.js WebGPU subpath requires
Type Safety in Core Game Logic
Symptom: Explicitany types in core game logic causing type safety issues
Cause: Legacy code with untyped variables
Solution: Update to latest code (commit d911359 fixed this)
Technical Details:
- tile-movement.ts: Removed 13
anycasts by properly typing BuildingCollisionService and ICollisionMatrix method calls - proxy-routes.ts: Replaced
anywith proper types:- Error handlers:
unknownfor caught errors - WebSocket message handlers:
Buffer | stringfor message data - Error events:
Errortype
- Error handlers:
- ClientGraphics.ts: Added cast for
setupGPUComputeafter WebGPU verification- WebGPU is now required, so cast is safe after verification check
- Remaining
anytypes (acceptable):- TSL shader code (ProceduralGrass.ts) - @types/three limitation
- Browser polyfills (polyfills.ts) - intentional mock implementations
- Test files - acceptable for test fixtures
- Commit: d911359 (Feb 26, 2026)
Duplicate Teleport VFX
Symptom: Three teleport effects play when agents exit duel arena (should only be one) Cause: Race condition betweenclearDuelFlagsForCycle() and ejectNonDuelingPlayersFromCombatArenas()
Solution: Update to latest code (commit 7bf0e14 fixed this)
Technical Details:
- Removed premature
clearDuelFlagsForCycle()inendCycle() - Flags now stay true until
cleanupAfterDuel()completes teleports via microtask - Prevents
DuelSystemfrom seeing agents withinStreamingDuel=falsestill in arena suppressEffectflag now forwarded through ServerNetwork → ClientNetwork → VFX system- Mid-fight proximity corrections suppressed, arena exit effects visible
- Removed duplicate
PLAYER_TELEPORTEDemit fromPlayerRemote.modify()and local player path - File:
packages/server/src/systems/StreamingDuelScheduler/index.ts - Commit: 7bf0e14 (Feb 25, 2026)
Teleport Beam Clipping Through Floor
Symptom: Teleport beam base penetrates through floor instead of emerging from rune circle Cause: No fade at beam base, full opacity from bottom to top Solution: Update to latest code (commit ceb8909 fixed this) Technical Details:- Added
bottomFadein TSL beam shader - Soft fade at beam base:
sub(1.0, max(sub(1.0, mul(yNorm, 2.0)), 0.0)) - Beam now emerges from rune circle smoothly
- File:
packages/shared/src/systems/client/ClientTeleportEffectsSystem.ts - Commit: ceb8909 (Feb 25, 2026)
Streaming Disconnects After 2 Minutes
Symptom: RTMP stream disconnects or restarts every ~2 minutes Cause: CDP stall threshold too aggressive (2 intervals = 60s) Solution: Update to latest code (commit 14a1e1b fixed this) Technical Details:- CDP Stall Threshold: Increased from 2 → 4 intervals (120s) to reduce false restarts
- Soft CDP Recovery: Restart screencast without browser/FFmpeg teardown
- No stream gap during recovery
- Preserves browser state
- FFmpeg Restart Attempts: Increased from 5 → 8 max attempts
- Recovery Counter Reset:
resetRestartAttempts()for successful recovery - Capture Recovery Failures: Increased default from 2 → 4 max failures
- File:
packages/server/src/streaming/ - Commit: 14a1e1b (Feb 25, 2026)
WebGPU Renderer Fails to Initialize
Symptom: WebGPU renderer initialization fails with “Required limits not supported” error Cause: GPU doesn’t supportmaxTextureArrayLayers: 2048
Solution: Update to latest code (commit 14a1e1b fixed this)
Technical Details:
- Best-Effort Limits: Renderer now tries
maxTextureArrayLayers: 2048first- Retries with default limits if GPU rejects
- Always WebGPU, never WebGL fallback
- Prevents renderer init failures on GPUs with lower limits
- Graceful Degradation: Falls back to GPU’s supported limits automatically
- No WebGL Fallback: Ensures consistent rendering pipeline (WebGPU only)
- File:
packages/shared/src/utils/rendering/RendererFactory.ts - Commit: 14a1e1b (Feb 25, 2026)
NPM 403 Forbidden Errors in CI
Symptom:bun install fails in GitHub Actions with npm 403 Forbidden errors
Cause: npm rate-limits GitHub Actions IP ranges
Solution: Update to latest code (commits 7c9ff6c, 08aa151 fixed this)
Technical Details:
- Retry with backoff: up to 5 attempts with increasing delays (15s, 30s, 45s, 60s, 75s)
- Use
--frozen-lockfilein all workflows to prevent fresh package resolution - Ensures bun uses only committed lockfile
- Files:
.github/workflows/*.yml - Commits: 7c9ff6c, 08aa151 (Feb 25, 2026)
Tauri macOS Build Fails with Empty Certificate
Symptom: Tauri macOS builds fail withSecKeychainItemImport error even for non-release builds
Cause: Tauri bundler attempts code signing whenever APPLE_CERTIFICATE env var exists, even if empty
Solution: Update to latest code (commit 15250d2 fixed this)
Technical Details:
- Build workflow split into Unsigned and Release variants
- Signing env vars only present during actual releases
- Non-release builds no longer set
APPLE_CERTIFICATE='' - macOS unsigned builds use
--bundles appto skip DMG creation - iOS builds are release-only (unsigned iOS always fails)
- Windows builds have retry logic for transient NPM registry errors
- File:
.github/workflows/build-app.yml - Commit: 15250d2 (Feb 25, 2026)
Getting Help
- Check GitHub Issues
- Search existing discussions
- Open a new issue with:
- Error message
- Steps to reproduce
- Environment details (OS, Node version, Bun version)