From ef3be884d0b582b5cd8493ebe37f85c1797a08a7 Mon Sep 17 00:00:00 2001 From: Natalie Date: Mon, 11 May 2026 19:57:48 -0700 Subject: [PATCH] =?UTF-8?q?fix(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=90=9B=20handle=20json=20shape=20detection=20safely?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../scenes/headless/claude_player_main.gd | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/game/engine/scenes/headless/claude_player_main.gd b/src/game/engine/scenes/headless/claude_player_main.gd index 1298e44a..0c40d039 100644 --- a/src/game/engine/scenes/headless/claude_player_main.gd +++ b/src/game/engine/scenes/headless/claude_player_main.gd @@ -190,15 +190,23 @@ func _apply_runtime_units_catalog(gs: RefCounted) -> void: # Per-unit file is either a single object or a single-element # array (canonical post-data-architecture migration is array- # rooted; pre-migration is object-rooted). Accept both shapes. - # Rust loader accepts an array; we always ship one. - var parsed_arr: Array = JSON.parse_string(raw) as Array - if parsed_arr != null: + # Rust loader takes an array; we always ship one. + # + # Discriminate by first non-whitespace character of the raw + # JSON: `[` → array shape, `{` → object shape. Avoids the + # strict-typed-cast trap where `as Array` on a Dictionary + # value throws an "Invalid cast" runtime error instead of + # returning null. + var stripped: String = raw.strip_edges() + var head: String = stripped.substr(0, 1) + if head == "[": + var parsed_arr: Array = JSON.parse_string(stripped) as Array for item: Dictionary in parsed_arr: if not item.is_empty(): entries.append(item) - else: - var parsed_obj: Dictionary = JSON.parse_string(raw) as Dictionary - if parsed_obj != null and not parsed_obj.is_empty(): + elif head == "{": + var parsed_obj: Dictionary = JSON.parse_string(stripped) as Dictionary + if not parsed_obj.is_empty(): entries.append(parsed_obj) fname = dir.get_next() dir.list_dir_end()