Skip to content

validator: dangling children references (element IDs that don't exist in elements) are not caught #136

Description

@CryptoExplor

Problem

In pkgs/snap/src/validator.ts, validateStructure checks element count, children count, and nesting depth — but it does not validate that the IDs listed in an element's children array actually exist in ui.elements.

This means a snap with dangling child references passes validation:

{
  "version": "2.0",
  "ui": {
    "root": "container",
    "elements": {
      "container": {
        "type": "stack",
        "props": { "direction": "vertical" },
        "children": ["title", "nonexistent_element"]
      },
      "title": {
        "type": "text",
        "props": { "content": "Hello" }
      }
    }
  }
}

In the above, "nonexistent_element" is referenced in container.children but does not exist in elements. validateStructure will not catch this — measureDepth short-circuits on missing IDs (if (!el?.children?.length) return 0) rather than raising an error, which silently ignores the dangling reference.

The client renderer will either crash, skip the missing element, or render an error state. Catching this at validation time gives snap authors a clear error message instead of a silent runtime failure.

Proposed Fix

Add a pass inside validateStructure that checks all child IDs in every element against the keys of ui.elements:

for (const [id, el] of Object.entries(elements)) {
  if (el.children) {
    for (const childId of el.children) {
      if (!(childId in elements)) {
        issues.push({
          code: "custom",
          message: `Element "${id}" references unknown child "${childId}"`,
          path: ["ui", "elements", id, "children"],
        });
      }
    }
  }
}

Affected File

pkgs/snap/src/validator.tsvalidateStructure function

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions