Skip to content

Blocks become invisible when loaded from XML with mismatched connection types #9588

@periperidev

Description

@periperidev

Check for duplicates

  • I have searched for similar issues before opening a new one.

Description

When loading workspace XML that contains a block connected to an input with an incompatible type, the child block becomes completely invisible. It still exists in the workspace data but has no visual representation.

Expected behavior

When a connection fails due to a type mismatch during XML loading, the child block should still be visible on the workspace as a disconnected/orphan block

Actual behavior

The block exists in the workspace's internal state but is never visually rendered. It becomes a "ghost block".

The ghost blocks are still returned by workspace.getTopBlocks() and pass isEnabled() checks. In our application, we have a validation step that checks for detached enabled blocks:

  const topLevelBlocks = workspace
    .getTopBlocks(false)
    .filter((block) => !block.getInheritedDisabled() && block.isEnabled());

  if (topLevelBlocks.length > 1) {
    return ["Detached, enabled blocks not supported!"];
  }

This validation fires because the ghost blocks exist as enabled top-level blocks in the data model but the user cannot see them on the workspace to fix or remove them. The user is told they have detached enabled blocks, but these blocks are invisible.

We later built a custom post-load step that walks all connections, checks type compatibility, and manually disconnects mismatched blocks. However, even with this workaround, the disconnected blocks do not become visible on the same load, they remain as ghost blocks. They only become visible orphans after the workspace is re-saved and triggered the workspace to reload again and we can't explicitly use this as workaround for our users as this will cause bigger problem if the input with detached values is mark as required input.

How we discovered this

In our application, users can change a data type on one tab (e.g., from Long to Int) while a visual programming editor (where blockly is used to config behavior) on another tab is closed. When the editor tab reopens, the saved XML is loaded, and any blocks that were previously valid but are
now type-incompatible silently vanish.

Version: 12.3.1

Reproduction steps

  1. Define two block types with different types:
    • Block A: has a value input that accepts "Int"
    • Block B: has an output of type "Long"
  2. Create workspace XML where Block B is nested inside Block A's value input:
3. Load the XML into a workspace using domToWorkspace 4. Block B is now invisible — it doesn't appear anywhere on the workspace. However, calling workspace.getTopBlocks() shows it still exists in memory.

Priority

Its not a app-crashing kind of issue. But its an important one to be addressed when possible. We don't have any workaround to address right now. And it is causing confusion.

Stack trace

Screenshots

No response

Browsers

Chrome desktop

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue: bugDescribes why the code or behaviour is wrongissue: triageIssues awaiting triage by a Blockly team member

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions