{"record":{"id":"da11f886b5bfba82","repo":"apache/beam","slug":"node-id-cannot-be-empty","errorCode":null,"errorMessage":"Node ID cannot be empty","messagePattern":"Node ID cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/apache_beam_jupyterlab_sidepanel/yaml_parse_utils.py","lineNumber":36,"sourceCode":"\nimport yaml\n\nimport apache_beam as beam\nfrom apache_beam.yaml.main import build_pipeline_components_from_yaml\n\n# ======================== Type Definitions ========================\n\n\n@dataclass\nclass NodeData:\n  id: str\n  label: str\n  type: str = \"\"\n\n  def __post_init__(self):\n    # Ensure ID is not empty\n    if not self.id:\n      raise ValueError(\"Node ID cannot be empty\")\n\n\n@dataclass\nclass EdgeData:\n  source: str\n  target: str\n  label: str = \"\"\n\n  def __post_init__(self):\n    if not self.source or not self.target:\n      raise ValueError(\"Edge source and target cannot be empty\")\n\n\nclass FlowGraph(TypedDict):\n  nodes: list[dict[str, Any]]\n  edges: list[dict[str, Any]]\n\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/apache_beam_jupyterlab_sidepanel/yaml_parse_utils.py#L18-L54","documentation":"NodeData.__post_init__ (a dataclass validator) raises this ValueError when a node parsed from the SidePanel YAML graph definition has an empty id. IDs are required keys used to link nodes and edges in the interactive graph, so an empty one is rejected immediately at object construction.","triggerScenarios":"Defining a node in the SidePanel YAML with a missing or empty 'id' field (id: '' or the key omitted), then parsing it via yaml_parse_utils, which constructs NodeData(id=...) and triggers __post_init__.","commonSituations":"Hand-editing the notebook/SidePanel YAML and deleting the id line; generating YAML programmatically where id defaults to empty string; copy-pasting a node template and forgetting to fill in the id.","solutions":["Give every node in the YAML a non-empty unique id field.","Validate the YAML before loading (assert each node has a truthy id).","Fix programmatic YAML generation so id is always populated.","Add a schema check step that fails early with the offending node name/index."],"exampleFix":"// before (yaml)\nnodes:\n  - label: Inspect\n    type: transform\n// after\nnodes:\n  - id: node-1\n    label: Inspect\n    type: transform","handlingStrategy":"validation","validationCode":"def validate_nodes(nodes):\n    for i, n in enumerate(nodes):\n        assert n.get('id'), f'node[{i}] has empty id: {n}'","typeGuard":"def node_is_valid(n: dict) -> bool:\n    return bool(isinstance(n, dict) and n.get('id'))","tryCatchPattern":"try:\n    node = NodeData(id=node_dict.get('id', ''), label=node_dict.get('label', ''), type=node_dict.get('type', ''))\nexcept ValueError as e:\n    raise YamlSchemaError(f'Bad node in SidePanel YAML: {node_dict}') from e","preventionTips":["Always include a non-empty id for each node in the YAML","Validate the YAML schema before parsing","Avoid templated YAML with empty placeholder ids","Keep node ids unique and immutable once referenced by edges"],"tags":["python","yaml","validation","jupyterlab","apache-beam"],"backgroundTag":"empty-required-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}