Skip to content

[QA] Runtime error in Bevy editor is silent - scene doesn't stop, no user notificationΒ #1479

Description

@balducciv

πŸ› οΈ Build version:

Decentraland Creator Hub 0.45.0 (fix/bevy branch) β€” PR #1463, item "Runtime error handling" (#1448)

πŸ“” Issue Description:

Per PR #1463's description, #1448 should notify the user and stop the Bevy scene when a genuine runtime error occurs (as opposed to a build/bundling failure, which is handled separately). Tested with a scene containing a visibly spinning box and a deliberate throw new Error(...) fired from an engine.addSystem at a fixed, known time (t=5s). In the Bevy editor's own Play mode, the error had no effect at all: the box kept spinning continuously past t=5s with no visible slowdown, freeze, or change, and no notification/toast appeared anywhere in the editor UI.

πŸ‘£ STR:

  1. Create a scene with a visible entity that updates every frame (e.g. a box rotating via engine.addSystem) and a deliberate throw new Error(...) inside that same system, timed to fire at a known point (e.g. t=5s, confirmed via a console.log timer)
  2. Open the scene in the Bevy editor and hit Play (the editor's own toolbar button β€” not the top-bar PREVIEW/scene-preview flow, which runs a separate Explorer-style runtime and is out of scope for this fix)
  3. Let the scene run past the error's trigger time
  4. Observe the viewport and editor UI for any notification, freeze, or stop

βœ”οΈ Expected Result:

At t=5s, the user should be notified (a toast/message) and the Bevy scene should stop β€” the spinning box should freeze in place.

❌ Actual Result with evidence:

The box kept spinning continuously with no visible change at t=5s or after. No notification or toast appeared in the editor. The scene behaved exactly as if the error never occurred.
[Test scene code available on request/attached separately]

βž— Reproduction:

πŸ” Always

πŸ–₯️ Operative system and additional Notes:

Mac [confirm chip]. Found while validating PR #1463, item "Runtime error handling" (#1448). Note: the same deliberate error, when triggered via the top-bar PREVIEW/scene-preview flow instead of the Bevy editor's Play, logs correctly to the console (confirmed via Player.log β€” Unity/Explorer stack trace) but likewise never stops that runtime either β€” however that flow is a separate Explorer-style runtime, not the Bevy engine, so it's out of scope for #1448 and included here only for context, not as part of the bug's evidence.

Scene console

[LOG] [09:43:34] [Log] SceneLog: t = 329s
[LOG] [09:43:35] [Log] SceneLog: t = 330s
[LOG] [09:43:36] [Log] SceneLog: t = 331s
[LOG] [09:43:37] [Log] SceneLog: t = 332s
[LOG] [09:43:38] [Log] SceneLog: UnityOpsApi initialized
[LOG] [09:43:39] [Log] SceneLog: t = 1s
[LOG] [09:43:40] [Log] SceneLog: t = 2s
[LOG] [09:43:41] [Log] SceneLog: t = 3s
[LOG] [09:43:42] [Log] SceneLog: t = 4s
[LOG] [09:43:43] [Log] SceneLog: t = 5s
[ERROR] [09:43:43] [Error] Error: Deliberate test runtime error at t=5s
    at Object.fn (Script [19]:37986:13)
    at Object.update (Script [19]:33674:26)
    at async Object.onUpdate (Script [19]:48080:3)
    at async __internalOnUpdate (Script [22]:13:21)
[ERROR] [09:43:43] [Error]   at Cysharp.Threading.Tasks.UniTaskCompletionSourceCore`1[TResult].GetResult (System.Int16 token) [0x00000] in ./Library/PackageCache/com.cysharp.unitask@f026e068eaed/Runtime/UniTaskCompletionSource.cs:244 
  at Cysharp.Threading.Tasks.AutoResetUniTaskCompletionSource.GetResult (System.Int16 token) [0x00000] in ./Library/PackageCache/com.cysharp.unitask@f026e068eaed/Runtime/UniTaskCompletionSource.cs:406 
  at Cysharp.Threading.Tasks.UniTask+Awaiter.GetResult () [0x00000] in ./Library/PackageCache/com.cysharp.unitask@f026e068eaed/Runtime/UniTask.cs:312 
  at SceneRunner.SceneFacade.UpdateLoopAsync (System.Threading.CancellationToken ct) [0x00000] in /opt/workspace/workspace/a065372e-0c5f-4536-0000-0440104d155d.8c1273e985o/Explorer/Assets/DCL/Infrastructure/SceneRunner/SceneFacade.cs:233 
  at Cysharp.Threading.Tasks.CompilerServices.AsyncUniTask`1[TStateMachine].Run () [0x00000] in ./Library/PackageCache/com.cysharp.unitask@f026e068eaed/Runtime/CompilerServices/StateMachineRunner.cs:189 
  at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction (System.Action action, System.Boolean allowInlining, System.Threading.Tasks.Task& currentTask) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Threading.Tasks.Task.FinishContinuations () [0x00000] in <00000000000000000000000000000000>:0 
  at Cysharp.Threading.Tasks.TaskPool`1[T].TryPush (T item) [0x00000] in ./Library/PackageCache/com.cysharp.unitask@f026e068eaed/Runtime/TaskPool.cs:120 
  at System.Threading.Tasks.Task+DelayPromise.Complete () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00000] in <00000000000000000000000000000000>:0 
[LOG] [09:43:44] [Log] SceneLog: t = 6s
[LOG] [09:43:45] [Log] SceneLog: t = 7s
[LOG] [09:43:46] [Log] SceneLog: t = 8s
[LOG] [09:43:47] [Log] SceneLog: t = 9s
[LOG] [09:43:48] [Log] SceneLog: t = 10s
[LOG] [09:43:49] [Log] SceneLog: t = 11s
[LOG] [09:43:50] [Log] SceneLog: t = 12s
[LOG] [09:43:51] [Log] SceneLog: t = 13s
[LOG] [09:43:52] [Log] SceneLog: t = 14s
[LOG] [09:43:53] [Log] SceneLog: t = 15s
[LOG] [09:43:55] [Log] SceneLog: t = 16s
[LOG] [09:43:56] [Log] SceneLog: t = 17s
[LOG] [09:43:57] [Log] SceneLog: t = 18s
[LOG] [09:43:58] [Log] SceneLog: t = 19s
[LOG] [09:43:59] [Log] SceneLog: t = 20s
10.08.2026_09.43.18_REC.scene.console.error.mp4

Index TS:
index.ts

import { engine, Transform, MeshRenderer, Material } from '@dcl/sdk/ecs'
import { Quaternion, Color4 } from '@dcl/sdk/math'

export function main() {
	// your scene code here
	const spinner = engine.addEntity()
	Transform.create(spinner, { position: { x: 8, y: 1, z: 8 } })
	MeshRenderer.setBox(spinner)
	Material.setPbrMaterial(spinner, { albedoColor: Color4.create(1, 0, 0, 1) }) // red β€” easy to spot

	let elapsed = 0
	engine.addSystem((dt: number) => {
		elapsed += dt

		// Continuous visible rotation β€” if the scene genuinely "stops" after the
		// runtime error below, this should freeze mid-spin. If it keeps spinning,
		// the scene didn't actually stop despite the error being logged.
		const transform = Transform.getMutable(spinner)
		transform.rotation = Quaternion.fromEulerDegrees(0, (elapsed * 90) % 360, 0)

		if (elapsed % 1 < dt) {
			console.log(`t = ${Math.floor(elapsed)}s`)
		}

		if (elapsed > 5 && elapsed - dt <= 5) {
			throw new Error('Deliberate test runtime error at t=5s')
		}
	})
}
10.08.2026_09.46.39_REC.bevy.viewport.mp4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions