Skip to content

[Bug]: Parent and child tag IDs are swapped in the parent_tags DB table #997

@HeikoWasTaken

Description

@HeikoWasTaken

Checklist

  • I am using an up-to-date version.
  • I have read the documentation.
  • I have searched existing issues.

TagStudio Version

Alpha 9.5.2

Operating System & Version

Arch Linux (Kernel: 6.15.5-arch1-1)

Description

While comparing the tags and tag_parents tables within the ts_library.sqlite database, it appears that the parent and child tag IDs are reversed in the tag_parents table. This seems to happen with user-defined tags as well as the default Archived, Favourite and Meta Tags tags.

What's currently happening:
Child tag ID -> parent_id field
Parent tag ID -> child_id field

Expected Behavior

Parent and child tag IDs should be assigned to the corresponding fields within the tag_parents table.

What should be happening:
Parent tag ID -> parent_id field
Child tag ID -> child_id field

Steps to Reproduce

  1. Create a new tag.
  2. Create a second tag and set the first tag as a parent.
  3. Open the ts_library.sqlite database and observe the records in the tags table.
  4. Compare the tag IDs to to those in the tag_parents table.

Logs

Tag Editor Image
Database
ts_library.sqlite> SELECT * FROM tag_parents;
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
| 0         | 2        |
| 1         | 2        |
| 1001      | 1000     |
+-----------+----------+
3 rows in set
Time: 0.015s
ts_library.sqlite> SELECT * FROM tags;
+------+-----------+-----------+--------------------+------------+-------------+--------+-------------------+
| id   | name      | shorthand | color_namespace    | color_slug | is_category | icon   | disambiguation_id |
+------+-----------+-----------+--------------------+------------+-------------+--------+-------------------+
| 0    | Archived  | <null>    | tagstudio-standard | red        | 0           | <null> | <null>            |
| 1    | Favorite  | <null>    | tagstudio-standard | yellow     | 0           | <null> | <null>            |
| 2    | Meta Tags | <null>    | <null>             | <null>     | 1           | <null> | <null>            |
| 1000 | parent    |           | <null>             | <null>     | 0           | <null> | <null>            |
| 1001 | child     |           | <null>             | <null>     | 0           | <null> | <null>            |
+------+-----------+-----------+--------------------+------------+-------------+--------+-------------------+
5 rows in set
Time: 0.003s
TagStudio
Using CPython 3.12.11
Creating virtual environment at: .venv
warning: No `requires-python` value found in the workspace. Defaulting to `>=3.12`.
      Built tagstudio @ file:///data/1/Projects/gallery/TagStudio
░░░░░░░░░░░░░░░░░░░░ [0/30] Installing wheels...                                                                                                              warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.
         If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
Installed 30 packages in 382ms
2025-07-23 18:26:47 [info     ] [FFmpeg] Using FFprobe location: ffprobe (Found)
2025-07-23 18:26:47 [info     ] [FFmpeg] Using FFmpeg location: ffmpeg (Found)
/data/1/Projects/gallery/TagStudio/.venv/lib/python3.12/site-packages/pydub/utils.py:300: SyntaxWarning: invalid escape sequence '\('
  m = re.match('([su]([0-9]{1,2})p?) \(([0-9]{1,2}) bit\)$', token)
/data/1/Projects/gallery/TagStudio/.venv/lib/python3.12/site-packages/pydub/utils.py:301: SyntaxWarning: invalid escape sequence '\('
  m2 = re.match('([su]([0-9]{1,2})p?)( \(default\))?$', token)
/data/1/Projects/gallery/TagStudio/.venv/lib/python3.12/site-packages/pydub/utils.py:310: SyntaxWarning: invalid escape sequence '\('
  elif re.match('(flt)p?( \(default\))?$', token):
/data/1/Projects/gallery/TagStudio/.venv/lib/python3.12/site-packages/pydub/utils.py:314: SyntaxWarning: invalid escape sequence '\('
  elif re.match('(dbl)p?( \(default\))?$', token):
2025-07-23 18:26:47 [info     ] [ResourceManager] Resources Registered: count=31
2025-07-23 18:26:47 [info     ] [Settings] Global Settings File Path not specified, using default
2025-07-23 18:26:47 [info     ] [Settings] Reading Global Settings File path=PosixPath('/home/heiko/.config/TagStudio/settings.toml')
2025-07-23 18:26:47 [info     ] [Cache] Cache File not specified, using default one filename=/home/heiko/.config/TagStudio/TagStudio.ini
2025-07-23 18:26:47 [info     ] [Config] Thumbnail cache size limit: 500 MB
2025-07-23 18:26:49 [error    ] Path does not exist.           open_path=None
2025-07-23 18:26:49 [error    ] TagStudio folder does not exist. library_path=PosixPath('/home/heiko/Projects/gallery/data/mocks/3') ts_folder=.TagStudio
2025-07-23 18:29:09 [info     ] creating library directory     dir=PosixPath('/home/heiko/Projects/gallery/data/mock/.TagStudio')
2025-07-23 18:29:09 [info     ] [Library] Opening SQLite Library connection_string=sqlite:////home/heiko/Projects/gallery/data/mock/.TagStudio/ts_library.sqlite library_dir=PosixPath('/home/heiko/Projects/gallery/data/mock')
2025-07-23 18:29:09 [info     ] [Library] DB_VERSION: 0       
2025-07-23 18:29:09 [info     ] [Library] Creating DB tables...
2025-07-23 18:29:10 [info     ] Directory scan time            duration=0.0027179718017578125 files_not_in_lib=[] files_scanned=0 path=PosixPath('/home/heiko/Projects/gallery/data/mock')
2025-07-23 18:29:10 [warning  ] [PanelModal] add_callback not implemented for FileExtensionModal
2025-07-23 18:29:10 [info     ] finished counting (0 seconds) 
2025-07-23 18:29:10 [info     ] searching library              filter=BrowsingState(page_index=0, sorting_mode=<SortingModeEnum.DATE_ADDED: 'file.date_added'>, ascending=True, query=None) query_full="SELECT DISTINCT entries.id, entries.folder_id, entries.path, entries.filename, entries.suffix, entries.date_created, entries.date_modified, entries.date_added \nFROM entries \nWHERE (entries.suffix NOT IN ('.json', '.xmp', '.aae')) ORDER BY entries.id ASC\n LIMIT 100 OFFSET 0"
2025-07-23 18:29:10 [info     ] SQL Execution finished (0 seconds)
2025-07-23 18:29:10 [info     ] items to render                count=0
2025-07-23 18:29:10 [info     ] [QtDriver] Loading Entries... 
2025-07-23 18:29:10 [info     ] [QtDriver] Building Filenames...
2025-07-23 18:29:10 [info     ] [QtDriver] Done! Processing ItemThumbs...
2025-07-23 18:30:30 [info     ] [TagSearchPanel] Updating tag limit
2025-07-23 18:30:30 [info     ] [TagSearchPanel] Updating Tags
2025-07-23 18:30:30 [info     ] searching tags                 limit=25 results=2 search=None statement='SELECT tags.id, tags.name, tags.shorthand, tags.color_namespace, tags.color_slug, tags.is_category, tags.icon, tags.disambiguation_id, tag_colors_1.slug, tag_colors_1.namespace, tag_colors_1.name AS name_1, tag_colors_1."primary", tag_colors_1.secondary, tag_colors_1.color_border \nFROM tags LEFT OUTER JOIN tag_aliases ON tags.id = tag_aliases.tag_id LEFT OUTER JOIN tag_colors AS tag_colors_1 ON tag_colors_1.namespace = tags.color_namespace AND tag_colors_1.slug = tags.color_slug ORDER BY lower(tags.name)\n LIMIT :param_1'
2025-07-23 18:30:35 [error    ] [BuildTag] Could not access Tag member attributes error=AttributeError("'NoneType' object has no attribute 'color'")
2025-07-23 18:30:35 [info     ] [TagColorPreview] Setting tag color primary=None secondary=None
2025-07-23 18:30:35 [info     ] [BuildTagPanel] Setting Tag    tag=<Tag ID: None Name: New Tag>
2025-07-23 18:30:35 [info     ] [TagColorPreview] Setting tag color primary=None secondary=None
2025-07-23 18:30:35 [warning  ] [PanelModal] add_callback not implemented for BuildTagPanel
2025-07-23 18:30:47 [info     ] built tag                      tag=<Tag ID: None Name: parent>
2025-07-23 18:30:47 [info     ] [TagSearchPanel] Updating Tags
2025-07-23 18:30:47 [info     ] searching tags                 limit=25 results=2 search= statement='SELECT tags.id, tags.name, tags.shorthand, tags.color_namespace, tags.color_slug, tags.is_category, tags.icon, tags.disambiguation_id, tag_colors_1.slug, tag_colors_1.namespace, tag_colors_1.name AS name_1, tag_colors_1."primary", tag_colors_1.secondary, tag_colors_1.color_border \nFROM tags LEFT OUTER JOIN tag_aliases ON tags.id = tag_aliases.tag_id LEFT OUTER JOIN tag_colors AS tag_colors_1 ON tag_colors_1.namespace = tags.color_namespace AND tag_colors_1.slug = tags.color_slug ORDER BY lower(tags.name)\n LIMIT :param_1'
2025-07-23 18:30:49 [error    ] [BuildTag] Could not access Tag member attributes error=AttributeError("'NoneType' object has no attribute 'color'")
2025-07-23 18:30:49 [info     ] [TagColorPreview] Setting tag color primary=None secondary=None
2025-07-23 18:30:49 [info     ] [BuildTagPanel] Setting Tag    tag=<Tag ID: None Name: New Tag>
2025-07-23 18:30:49 [info     ] [TagColorPreview] Setting tag color primary=None secondary=None
2025-07-23 18:30:49 [warning  ] [PanelModal] add_callback not implemented for BuildTagPanel
2025-07-23 18:30:55 [info     ] [TagSearchPanel] Updating tag limit
2025-07-23 18:30:55 [info     ] [TagSearchPanel] Updating Tags
2025-07-23 18:30:55 [info     ] searching tags                 limit=25 results=2 search=None statement='SELECT tags.id, tags.name, tags.shorthand, tags.color_namespace, tags.color_slug, tags.is_category, tags.icon, tags.disambiguation_id, tag_colors_1.slug, tag_colors_1.namespace, tag_colors_1.name AS name_1, tag_colors_1."primary", tag_colors_1.secondary, tag_colors_1.color_border \nFROM tags LEFT OUTER JOIN tag_aliases ON tags.id = tag_aliases.tag_id LEFT OUTER JOIN tag_colors AS tag_colors_1 ON tag_colors_1.namespace = tags.color_namespace AND tag_colors_1.slug = tags.color_slug ORDER BY lower(tags.name)\n LIMIT :param_1'
2025-07-23 18:31:03 [info     ] add_parent_tag_callback        tag_id=1000
QWidget::setTabOrder: 'first' and 'second' must be in the same window
2025-07-23 18:31:25 [info     ] built tag                      tag=<Tag ID: None Name: child>
2025-07-23 18:31:25 [info     ] [TagSearchPanel] Updating Tags
2025-07-23 18:31:25 [info     ] searching tags                 limit=25 results=2 search= statement='SELECT tags.id, tags.name, tags.shorthand, tags.color_namespace, tags.color_slug, tags.is_category, tags.icon, tags.disambiguation_id, tag_colors_1.slug, tag_colors_1.namespace, tag_colors_1.name AS name_1, tag_colors_1."primary", tag_colors_1.secondary, tag_colors_1.color_border \nFROM tags LEFT OUTER JOIN tag_aliases ON tags.id = tag_aliases.tag_id LEFT OUTER JOIN tag_colors AS tag_colors_1 ON tag_colors_1.namespace = tags.color_namespace AND tag_colors_1.slug = tags.color_slug ORDER BY lower(tags.name)\n LIMIT :param_1'
2025-07-23 18:35:04 [info     ] Closing Library...            
2025-07-23 18:35:09 [info     ] No Library to Close           
2025-07-23 18:35:09 [info     ] [SHUTDOWN] Ending Thumbnail Threads...

Metadata

Metadata

Assignees

No one assigned

    Labels

    TagStudio: LibraryRelating to the TagStudio library systemType: BugSomething isn't working as intended

    Type

    Projects

    Status

    ✅ Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions