lllyasviel/Fooocus · critical · ValueError

Max depth of recursive function `tie_encoder_to_decoder` rea

Error message

Max depth of recursive function `tie_encoder_to_decoder` reached. It seems that there is a circular dependency between two or more `nn.Modules` of your model.

What it means

tie_encoder_to_decoder_recursively walks the encoder and decoder module trees in lockstep to tie (share) weights; if the recursion depth exceeds 500 it concludes the module graph contains a cycle (a module that contains itself as a child), which would recurse forever. In practice this is raised when the structures of the two modules diverge so badly that name-based matching descends into mismatched subtrees indefinitely.

Source

Thrown at extras/BLIP/models/blip_pretrain.py:321

            all_encoder_weights = set([module_name + "/" + sub_name for sub_name in encoder_modules.keys()])
            encoder_layer_pos = 0
            for name, module in decoder_modules.items():
                if name.isdigit():
                    encoder_name = str(int(name) + encoder_layer_pos)
                    decoder_name = name
                    if not isinstance(decoder_modules[decoder_name], type(encoder_modules[encoder_name])) and len(
                        encoder_modules
                    ) != len(decoder_modules):
                        # this can happen if the name corresponds to the position in a list module list of layers
                        # in this case the decoder has added a cross-attention that the encoder does not have
                        # thus skip this step and subtract one layer pos from encoder
                        encoder_layer_pos -= 1
                        continue
                elif name not in encoder_modules:
                    continue
                elif depth > 500:
                    raise ValueError(
                        "Max depth of recursive function `tie_encoder_to_decoder` reached. It seems that there is a circular dependency between two or more `nn.Modules` of your model."
                    )
                else:
                    decoder_name = encoder_name = name
                tie_encoder_to_decoder_recursively(
                    decoder_modules[decoder_name],
                    encoder_modules[encoder_name],
                    module_name + "/" + name,
                    uninitialized_encoder_weights,
                    skip_key,
                    depth=depth + 1,
                )
                all_encoder_weights.remove(module_name + "/" + encoder_name)

            uninitialized_encoder_weights += list(all_encoder_weights)

    # tie weights recursively
    tie_encoder_to_decoder_recursively(decoder, encoder, base_model_prefix, uninitialized_encoder_weights, skip_key)  

View on GitHub (pinned to ae05379cc9)

Solutions

  1. Check that encoder and decoder are the intended objects — you must not pass the same module (or a module containing the other) for both
  2. Use the skip_key argument (e.g. skip_key='bert') to stop recursion at mismatched shared submodules, as BLIP's pretrain code does
  3. Verify config.json / model construction matches the checkpoint architecture (num layers, layer names) so lockstep traversal stays aligned
  4. Inspect model.named_modules() for duplicated/self-referential entries introduced by custom code

Example fix

// before
tie_encoder_to_decoder(model.decoder, model.encoder)  # incompatible trees

// after
tie_encoder_to_decoder(model.decoder, model.encoder, skip_key='bert')
Defensive patterns

Strategy: validation

Validate before calling

def can_tie_safely(encoder, decoder, skip_key=None):
    enc_names = [n for n, _ in encoder.named_modules() if skip_key not in n]
    dec_names = [n for n, _ in decoder.named_modules() if skip_key not in n]
    return set(enc_names) & set(dec_names) != set()  # rough compatibility probe

Try / catch

try:
    tie_encoder_to_decoder(decoder, encoder, skip_key='bert')
except ValueError as e:
    if 'Max depth' in str(e):
        raise RuntimeError('encoder/decoder module trees incompatible; check architectures') from e
    raise

Prevention

When it happens

Trigger: Calling tie_encoder_to_decoder(decoder, encoder) where encoder and decoder are architecturally incompatible (e.g. tying a BertModel encoder to a decoder whose layer list lengths/names mismatch), or where a module was registered as its own child (circular nn.Module references), causing depth to grow past 500.

Common situations: Loading a BLIP pretrained checkpoint into a model config with different num_hidden_layers or renamed submodules; passing the decoder itself (or a wrapper containing it) as the encoder argument; custom modifications that add a module attribute pointing back to a parent.

Related errors


AI-assisted analysis of lllyasviel/Fooocus@ae05379cc9 (2026-08-15). Data as JSON: /api/errors/408cb2ed8d5d3ac8. Report an issue: GitHub.