gaphor / gaphor

Gaphor is the simple modeling tool
https://gaphor.org
1.87k stars 201 forks source link

The files does not contain a valid Gaphor model #1928

Closed mcdigregorio closed 1 year ago

mcdigregorio commented 1 year ago

Describe the bug

After upgrading to Gaphor 2.13.0 from 2.11.0, getting a "The files does not contain a valid Gaphor model" message

To Reproduce

Steps to reproduce the behavior:

  1. Open Gaphor 2.13.0
  2. Try to open attached DemandSupply.gaphor file

Expected behavior

Expected model to open cleanly.

OS

Version

Version of Gaphor: 2.13.0

Additional information

It seems like all of my issues are tied to AssociationItems. I was able to setup a debug environment and grab some exceptions which led me to the below "bad" AssociationItems by id. I believe the core issues were missing "diagram" elements and missing "subject" elements.

  1. 58c9cc3c-62fb-11ed-8ada-acde48001122
    • Missing diagram element
  2. 6510dd3c-62fb-11ed-8ada-acde48001122
    • Missing diagram element
  3. 5fd55582-62fb-11ed-8ada-acde48001122
    • Missing subject element
  4. 764984be-62fb-11ed-8ada-acde48001122
    • Missing subject element
  5. 77957e0e-62fb-11ed-8ada-acde48001122
    • Missing subject element
  6. 4c2ef7da-62fc-11ed-8ada-acde48001122
    • Missing subject element
  7. 51e1b6e0-62fc-11ed-8ada-acde48001122
    • Missing subject element
  8. 631ae210-62fc-11ed-8ada-acde48001122

    • Missing subject element

    If I remove these elements from the .gaphor file I am able to open the model again. For reference I attached that working version in the .zip as DemandSupply_Working.gaphor.

    Does this seem like an issue tied to a corrupt gaphor file? Maybe I had a bad save prior? If so, is there any way to recover those "corrupt" elements?

At this point, losing these elements isn't a big deal for me, but just trying to decrease the likelihood it happens again.

GaphorFiles.zip

amolenaar commented 1 year ago

@mcdigregorio I'll have a look.

amolenaar commented 1 year ago

I had a look. It contained 2 associations that were missing a diagram and an association (+ 2 properties/ends) that had no properties at all. I'm curious how that happened, so far our property based tests haven't found this issue.

This is the resulting model: DemandSupply.zip

mcdigregorio commented 1 year ago

Thanks @amolenaar. I appreciate you looking at this. I'm also curious what happened, just figuring I did something weird on my end.

It it's any help these are the tracebacks I was dealing with:

Traceback (most recent call last):
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/ui/filemanager.py", line 153, in async_loader
    yield from open_model(encoding="utf-8")
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/ui/filemanager.py", line 195, in open_model
    for percentage in storage.load_generator(
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 271, in load_generator
    for percentage in load_elements_generator(
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 149, in load_elements_generator
    yield from _load_elements_and_canvasitems(
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 198, in _load_elements_and_canvasitems
    create_element(elem)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 188, in create_element
    diagram_id = elem.references["diagram"] #Invalid index?
                 ~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 'diagram'
Traceback (most recent call last):
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/ui/filemanager.py", line 153, in async_loader
    yield from open_model(encoding="utf-8")
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/ui/filemanager.py", line 195, in open_model
    for percentage in storage.load_generator(
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 271, in load_generator
    for percentage in load_elements_generator(
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/storage/storage.py", line 159, in load_elements_generator
    elem.element.postload()
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/association.py", line 118, in postload
    super().postload()
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/diagram/presentation.py", line 353, in postload
    postload_connect(self, self.tail, self._load_tail_connection)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/diagram/presentation.py", line 69, in postload_connect
    connect(item, handle, target)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/diagram/presentation.py", line 58, in connect
    connector.connect(sink)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/transaction.py", line 169, in _transactional
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/diagram/_connector.py", line 70, in connect
    adapter.connect(handle, sink.port)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/diagram/connectors.py", line 316, in connect
    self.connect_subject(handle)
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/classconnect.py", line 146, in connect_subject
    relation = self.relationship_or_new(head_end.subject, tail_end.subject)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/classconnect.py", line 115, in relationship_or_new
    relation: UML.Association | None = self.relationship(head_subject, tail_subject)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/classconnect.py", line 100, in relationship
    return next(
           ^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/classconnect.py", line 104, in <genexpr>
    if member_ends_match(a) and diagram not in a.presentation[:].diagram
       ^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/UML/classes/classconnect.py", line 86, in member_ends_match
    head_subject is subject.memberEnd[0].type
                    ~~~~~~~~~~~~~~~~~^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/core/modeling/collection.py", line 76, in __getitem__
    return self.items.__getitem__(key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/core/modeling/listmixins.py", line 263, in __getitem__
    return super().__getitem__(key)  # type: ignore[misc] # noqa: F821
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/michaeldigregorio/devspace/gaphorDev/gaphor/gaphor/core/modeling/listmixins.py", line 95, in __getitem__
    return super().__getitem__(key)  # type: ignore[misc] # noqa: F821
           ^^^^^^^^^^^^^^^^^^^^^^^^
IndexError: list index out of range
ArgInfo(args=['subject'], varargs=None, keywords=None, locals={'subject': <gaphor.UML.uml.Association element 5accbcb0-62fb-11ed-8ada-acde48001122>, 'head_subject': <gaphor.SysML.sysml.Block element b5cce3c4-3c31-11ed-827c-acde48001122>, 'tail_subject': <gaphor.UML.uml.Actor element 2a4dade8-73b3-11ec-85b5-acde48001122>})
amolenaar commented 1 year ago

I saw those during loading of the model too. What I'm wondering is how it ended up in the model like this before saving.

amolenaar commented 1 year ago

Those issues are remedied by #1942.