Error on importing scenes with cyclic dependencies

Hello!

I am just putting this tip here because I stumbled upon this issue recently while messing around, and while a couple topics on the matter exist on the forum, there is no real guided solution.

Load failed due to missing dependencies

What are mutual/circular/cyclic dependencies

As in the example of the above screenshot, it’s two objects, resources or scenes that reference each other. This is an issue because when loading, the editor will try to open mistake1.tscn which will make it load its dependencies, including mistake2.tscn which will make it load mistake1.tscn aaaaand that’s bad.

Note that the editor will happily let you create such a scenario, and it may very well work while you don’t close it. In the example above the scenes are linked via an @export

extends Node3D
@export var other_scene: PackedScene

So while the editor will fail to load, this will run fine without infinite recursion since the scenes are stored packed, so even if you create an instance of mistake1.tscn, it will only contain a packed version of mistake2.tscn which needs to be instantiated to create an instance of mistake1.tscn and get you into trouble.

How to fix the scenes

Backup your files.
We are going to edit the contents of the scenes so make backups, or accept that failure may result in loss of data. Use git if you don’t, it’s nifty.

In the scene file structure there will be two or more references to the specific link that cause your issue:

[gd_scene load_steps=3 format=3 uid="uid://c6gf4cigtxqhg"]

[ext_resource type="Script" uid="uid://ygxinjdvysua" path="res://mistake.gd" id="1_phx0m"]
[ext_resource type="PackedScene" uid="uid://dhr87x3qoh5m2" path="res://mistake2.tscn" id="2_hlmws"]

[node name="Mistake" type="Node3D"]
script = ExtResource("1_phx0m")
other_scene = ExtResource("2_hlmws")

First we have the declaration of the resource:

[ext_resource type="PackedScene" uid="uid://dhr87x3qoh5m2" path="res://mistake2.tscn" id="2_hlmws"]

And then, depending on your setup, you will have one or more places where this resource is used. You can track them down using the id in the declaration:

other_scene = ExtResource("2_hlmws")

Removing the declaration of the resource and is not enough, you have to also remove every one of its uses. Note that if you start the editor and you forgot one, the log window will tell you where in the file it is:


This means line 7

Once all traces of the resource are removed, the scene will load, and of course the inspector will show the @export empty

How to avoid this

There are many ways to have a mutual connection between two scenes. The mistake that prompted this post was because I was trying to link two rooms together, so a threshold object placed in room1 was referencing room2 and vise-versa.

In my case this was solved by using a path instead of a PackedScene:

@export_custom(PROPERTY_HINT_FILE, "*.tscn") var TargetRoomPath: String

Then when needed load and instantiate the scene. This way the editor will not try to preload the linked scenes.

Generally scenes should try to be as independent from each other as possible, and connections like this should be done at run time. Of course rules are made to be broken, but in cases like this it’s less about convenience and more about something that works at all :sweat_smile:

If you feel that you really need two scenes to be linked, try finding what exactly you need from scene2 when inside scene1 and you will often find that you don’t need to connect the whole scenes. Most of the time you can get away by sharing a common resource, a few @export, some signals … or sometimes the two scenes would rater be only one.

Go make games :v:

1 Like

It’s crazy that this still is an unsolved problem in Godot. If you want to corrupt your scene in seconds, just reference the scene within the scene. Doesn’t even need a second one.