Skip to content

bug: RelationshipManager.fetch()/add() give misleading errors when the node has no id #1153

Description

@PhillSimonds

Component

Python SDK

Infrahub SDK version

1.22.0

Current Behavior

When a RelationshipManager belongs to a node that has no id (e.g. a node built with client.create() but never save()d, so it was never persisted), editing the relationship produces two confusing errors that don't point at the real cause:

  • Error 1: node.rel.fetch()ValueError: At least one filter must be provided to get(): fetch() (infrahub_sdk/node/relationship.py:234) re-fetches the parent node via self.client.get(..., id=self.node.id, ...) (relationship.py:250). With id=None, get() has zero filters and raises the generic message from client.py:584. Nothing tells the user the problem is the node's missing id, or gives an indication of why that id might be missing (e.g. the node was created but not saved).
  • Error 2: node.rel.add(...)UninitializedError: Must call fetch() on RelationshipManager before editing members (relationship.py:296). This tells the user to call fetch(), but for a node with no id fetch() can't succeed either — so the two errors point at each other and give the user no clear path forward.

Expected Behavior

fetch() (and the add()/remove() guards) should detect the missing identifier and raise an actionable message instead of the generic filter error, e.g.:

Unable to fetch the 'members' relationship: this Parent has no ID, so it hasn't been saved to Infrahub yet (or wasn't loaded from it). Call .save() first, or fetch the node before accessing its relationships.

It would be nice if the message is phrased around "no ID to look it up by and the node is likely not yet persisted in infrahub." Just raising that the ID doesn't exist requires the user to think about why the ID doesn't exist. That could be confusing for a user who doesn't yet understand that .create() creates locally but does not save data to infrahub and that a call to .save() is required to generate the id in infrahub. The user might also not understand that node.rel fetches anything from infrahub, which is another thing the user needs to think through to understand why there is no id. There are cases in which the ID doesn't exist for other reasons, but the id normally doesn't exist because the node has not been saved, so a nudge to save the node (a quick why they are hitting this error) in addition to explaining the node does not yet have an id (the technical reason we cant fetch the node) is probably the right move so we make the SDK easy for users to consume, understand, and troubleshoot.

Steps to Reproduce

# Parent has a cardinality-many relationship "children"
parent = await client.create(kind="Parent", data={"name": "p1"})  # NOT saved -> parent.id is None

await parent.children.fetch()
# -> ValueError: At least one filter must be provided to get()

parent.children.add(some_child)
# -> UninitializedError: Must call fetch() on RelationshipManager before editing members
#    (but fetch() can't succeed either, since parent has no id)

Fix on the user side is to await parent.save() first (which backpopulates parent.id); the request here is only that the error message say so.

Additional Information

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working as expected

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions