{"record":{"id":"d7b2d75edd5b5e78","repo":"invoke-ai/InvokeAI","slug":"field-types-are-incompatible-edge","errorCode":null,"errorMessage":"Field types are incompatible ({edge})","messagePattern":"Field types are incompatible \\((.+?)\\)","errorType":"validation","errorClass":"InvalidEdgeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/shared/graph.py","lineNumber":1940,"sourceCode":"            not isinstance(destination_node, CollectInvocation) or edge.destination.field != ITEM_FIELD\n        ):\n            raise InvalidEdgeError(f\"Edge already exists ({edge})\")\n\n    def _validate_edge_would_not_create_cycle(self, edge: Edge) -> None:\n        graph = self.nx_graph_flat()\n        graph.add_edge(edge.source.node_id, edge.destination.node_id)\n        if not nx.is_directed_acyclic_graph(graph):\n            raise InvalidEdgeError(f\"Edge creates a cycle in the graph ({edge})\")\n\n    def _validate_edge_field_compatibility(\n        self, edge: Edge, source_node: BaseInvocation, destination_node: BaseInvocation\n    ) -> None:\n        if isinstance(destination_node, CallSavedWorkflowInvocation) and is_call_saved_workflow_dynamic_input(\n            edge.destination.field\n        ):\n            return\n        if not are_connections_compatible(source_node, edge.source.field, destination_node, edge.destination.field):\n            raise InvalidEdgeError(f\"Field types are incompatible ({edge})\")\n\n    def _validate_iterator_edge_rules(\n        self, edge: Edge, source_node: BaseInvocation, destination_node: BaseInvocation\n    ) -> None:\n        if isinstance(destination_node, IterateInvocation) and edge.destination.field == COLLECTION_FIELD:\n            err = self._is_iterator_connection_valid(edge.destination.node_id, new_input=edge.source)\n            if err is not None:\n                raise InvalidEdgeError(f\"Iterator input type does not match iterator output type ({edge}): {err}\")\n\n        if isinstance(source_node, IterateInvocation) and edge.source.field == ITEM_FIELD:\n            err = self._is_iterator_connection_valid(edge.source.node_id, new_output=edge.destination)\n            if err is not None:\n                raise InvalidEdgeError(f\"Iterator output type does not match iterator input type ({edge}): {err}\")\n\n    def _validate_collector_edge_rules(\n        self,\n        edge: Edge,\n        source_node: BaseInvocation,","sourceCodeStart":1922,"sourceCodeEnd":1958,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/shared/graph.py#L1922-L1958","documentation":"InvalidEdgeError raised by _validate_edge_field_compatibility() when are_connections_compatible() finds the edge's source output type incompatible with the destination input type. Dynamic inputs on CallSavedWorkflowInvocation nodes are exempt from this check.","triggerScenarios":"Calling g.add_edge() (or add_edge performed during deserialization) where the source field's output type doesn't match the destination field's input type, e.g. image output into a latents input.","commonSituations":"Connecting fields with similar names but different types, custom nodes whose types changed after an update, scripts wiring fields by name without checking types.","solutions":["Connect fields whose types actually match (check node field annotations)","Insert a conversion node (e.g. VAE encode/decode) between mismatched types","Update or pin the custom node pack that changed its field types","Use the UI's connection validation, which only offers compatible fields"],"exampleFix":"// before\ng.add_edge(load_image, \"image\", inpaint_mask, \"latents\")  # mismatch\n// after\nlatents = vae_encode(load_image, \"image\")\ng.add_edge(vae_encode, \"latents\", inpaint_mask, \"latents\")","handlingStrategy":"validation","validationCode":"from invokeai.app.services.shared.graph import are_connections_compatible\n\ndef can_connect(graph, src_id, src_field, dst_id, dst_field) -> bool:\n    return are_connections_compatible(\n        graph.get_node(src_id), src_field,\n        graph.get_node(dst_id), dst_field,\n    )\n\nassert can_connect(g, \"img_1\", \"image\", \"denoise_1\", \"image\")","typeGuard":"def fields_compatible(graph, edge) -> bool:\n    try:\n        return are_connections_compatible(\n            graph.get_node(edge.source.node_id), edge.source.field,\n            graph.get_node(edge.destination.node_id), edge.destination.field,\n        )\n    except NodeNotFoundError:\n        return False","tryCatchPattern":"from invokeai.app.services.shared.graph import InvalidEdgeError\n\ntry:\n    g.add_edge(src, src_field, dst, dst_field)\nexcept InvalidEdgeError as e:\n    if \"incompatible\" in str(e):\n        insert_conversion_node(src, dst)  # e.g. VAE encode/decode\n    else:\n        raise","preventionTips":["Check field types via get_output_field_type/get_input_field_type before wiring by name","Use the UI, which only offers type-compatible fields for connection","Re-validate workflows after upgrading custom node packs"],"tags":["invokeai","graph-validation","type-mismatch","edges"],"backgroundTag":"edge-type-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}