Drag and drop tag groups, crashes anki

Continuing the discussion from Can't drag and drop multiple tag groups, crashes Anki:

I finally managed to reproduce this issue and it’s weird to say the least.

Attached is a minimal apkg that should work (break): Upload files for free - broken1.apkg - ufile.io

If you try to move the tag group “Biologie” (Biology) from the msh::Semester_1::* tree to msh::Fächer::* it will crash with the same error.
Now here’s the part that makes it super weird: if you rename any tag in the tag struct (say turn msh into anything else like dae or Biologie to Biology it will work just fine.

I really hope you can reproduce it with this apkg because it took me forever to isolate…

Tag struct should look like this:

Here’s the exact error that pops up. I was also able to reproduce it on the latest beta version:

1 Like

It’s caused by case-sensitive matching somewhere. If you remove this tag from the note, run Check Database, then add the tag again as msh::Semester_1::Biologie::Mikrobiologie, the issue will go away.

@dae Rust shows rslib\src\tags\reparent.rs:66:78 as the source of the error.

This seems to fix it:

diff --git a/rslib/src/tags/reparent.rs b/rslib/src/tags/reparent.rs
index 5a1b73567..5d643379b 100644
--- a/rslib/src/tags/reparent.rs
+++ b/rslib/src/tags/reparent.rs
@@ -3,6 +3,8 @@
 
 use std::collections::HashMap;
 
+use unicase::UniCase;
+
 use super::join_tags;
 use super::matcher::TagMatcher;
 use crate::prelude::*;
@@ -62,8 +64,12 @@ impl Collection {
         // replace tags
         for mut note in matched_notes {
             let original = note.clone();
-            note.tags = matcher
-                .replace_with_fn(&note.tags, |cap| old_to_new_names.get(cap).unwrap().clone());
+            note.tags = matcher.replace_with_fn(&note.tags, |cap| {
+                old_to_new_names
+                    .get(&UniCase::new(cap.to_string()))
+                    .unwrap()
+                    .clone()
+            });
             note.set_modified(usn);
             self.update_note_tags_undoable(&note, original)?;
         }
@@ -80,13 +86,13 @@ impl Collection {
 fn old_to_new_names(
     tags_to_reparent: &[String],
     new_parent: Option<String>,
-) -> HashMap<&str, String> {
+) -> HashMap<UniCase<String>, String> {
     tags_to_reparent
         .iter()
         // generate resulting names and filter out invalid ones
         .flat_map(|source_tag| {
             reparented_name(source_tag, new_parent.as_deref())
-                .map(|output_name| (source_tag.as_str(), output_name))
+                .map(|output_name| (UniCase::new(source_tag.to_owned()), output_name))
         })
         .collect()
 }
2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.