Apparent bug in Ubuntu with LibreOffice causes citations to be unlinked on paste

I have a similar problem to that reported by others. I'm working in LibreOffice.
It's possible that I cut and pasted one section of my document from version saved as .docx but I don't think so, also the affected parts of my main document are too large for that to be the reason.
One possible cause is that I moved some sections around both by cutting and pasting and by using Navigator. My experience in the past, (and with a new test document) though is that this doesn't break links. However, due to the size of the current document, and perhaps corruption of the file, and bugs in the software, the cutting and pasting probably broke the links.
I attempted to cut and paste from a previous .odt version into the current document and the footnote references (Chicago note style) go from linked to unlinked when pasted.
On opening an older version I find that a few seemingly random citations in the footnotes are unlinked.
Cutting and pasting all content of the current document to an entirely new document allowed me to successfully cut and paste sections from an older version.
This suggests that possibly the Writer document had become corrupted.

However, Its likely this is a LibreOffice Ubuntu interaction bug.
See https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1852183
I downgraded to the more stable version 7.3.7.2 to be on the safe side.

Original issue while working with:
Zotero version: 6.0.18
LibreOffice Writer version: 7.4.2.3 / LibreOffice Community
Build ID: 40(Build:3)
Linux Mint 20.3 Cinnamon
Ubuntu package version: 1:7.4.2~rc3-0ubuntu0.20.04.1~lo1
Linux kernel 5.4.0-66-generic
  • Copying and pasting citations in LibreOffice (when citing as Reference marks in an .odt document) unlinks the newly pasted citations. This is a limitation of LibreOffice.
  • @adomasven, thanks for that confirmation. I see that in the Writer Navigator, we can view under Footnotes > References all of the ZOTERO_ITEM CSL_CITATION entries that correspond to a document's various citations.

    Is there a way to copy a citation code from here, paste it into a new footnote, and then turn the pasted text into a linked field?

    One use case would be instances where there's a complex citation that needs to be made in multiple places (maybe even multiple documents). A copy-and-paste process would obviate the need to reconstruct the citation from scratch.

    I've found how to turn text into field codes in Word. But I'm having trouble turning up the corresponding process for Writer.

    Thanks so much for any suggestions you may have!
  • When using libreoffice with reference marks to enter the citations. if you enter two identical references, then they will have different attributes (look in the navigator for the reference tag, the citation ids are different).
    Unfortunately, it appears that libreoffice does not allow two reference marks to have the same attributes - a situation that would occur with copy and paste. Cut and paste, however, does work as the reference marks are not duplicated.
    Hence, probably not a bug. But it certainly is a nuisance.

    As to the proposal by dstark, a macro could be written. This would need probably to be in python using citeproc-py (code is languishing well behind) or javascipt using citeproc.js (this is what zotero uses). If somebody has nothing better to do.....
  • @dstark Make sure you highlight some text in your document. Go to Insert -> Cross-Reference. Select "Set Reference" in the top window, then paste in the field code you want to copy in the Name field. At the end of the code there should be a 13 character long random string. Modify any characters in that string so that it isn't identical to the one you have copied. Press "Insert" in the dialog, then close it. You will have to refresh the document with Zotero and will get prompted about modified text, you should select "No" in that dialog.
  • Thanks, @adomasven. I think I follow all of that except for how I copy the field code in the first place (these are the entries beginning "ZOTERO_ITEM CSL_CITATION …" right?). I don't seem to be able to do that either from the navigator or from the Cross-reference dialogue.

    Am I just missing how to do this copy? Or is that not something that Writer supports?
  • I managed to get it working by doing:

    1) select where you want to insert the reference
    2) open Insert -> Cross-Reference -> Insert Reference
    3) click on the reference you need in the right panel
    4) click the mouse in the name panel and ctrl-a ctrl-c to copy the reference field
    5) go to Insert -> Cross-Reference -> Set Reference
    6) ctrl-v to paste the reference field into the name
    7) change one of more of the last letters at the end of the string (you should already see the end of the string in the name field)
    8) click on insert
    9) refresh the document with Zotero and and No in the dialog.

    After all that it would probably be quicker to insert the reference as usual from Zotero.
  • After all that it would probably be quicker to insert the reference as usual from Zotero.
    Totally agree, @gwyn-hopkins. My goodness. :-O But so appreciate your taking the time to point out how it could be done if one were really minded to.

    Thanks so much!
  • Ok. I quickly wrote a python macro to see if it was possible. As usual, the libreoffice api caused a lot of grief. A couple of libraries need adding (see start of code).
    This has only been tested with Apa6 style of citations e.g. (name et al., 2023). It will not work with numbered styles. You may get it to work with square bracket styles if you change the line with the # comment.
    It is written so that it should be easy to understand if you want to convert it to basic.The only problem may be checking in footnotes and endnotes which has to rely on an error generated when trying to compare text ranges (thrown when the ranges are in different text components), If you do not put references in footnotes or endnotes (who would?) then these sections can be omitted.




    import random
    import string
    import json

    def correct_references():
    document = XSCRIPTCONTEXT.getDocument()
    search_descriptor = document.createSearchDescriptor()
    search_descriptor.SearchRegularExpression = True

    reference_marks = document.ReferenceMarks

    for reference_mark in reference_marks:
    reference_mark_content = reference_mark.Name
    reference_mark_json, _ = reference_mark_content.rsplit(" ", 1)
    _, _, reference_mark_json = reference_mark_json.split(" ", 2)

    data_dictionary = json.loads(reference_mark_json, strict=False)
    plain_cite = data_dictionary["properties"]["plainCitation"]
    search_descriptor.SearchString = "\(" + plain_cite[1:-1] + "\)" #have to escape the parentheses
    search_found = document.findFirst(search_descriptor)

    while search_found:

    if not search_found.Start.ReferenceMark:

    n = 10
    characters = string.ascii_letters + string.digits
    randomChars = ''.join(random.choice(characters) for i in range(n))
    new_reference_mark_content = reference_mark_content[:-n] + randomChars
    new_reference_mark = document.createInstance("com.sun.star.text.ReferenceMark")
    new_reference_mark.Name = new_reference_mark_content

    if search_found.getText().supportsService("com.sun.star.text.CellProperties"):
    view_cursor = document.getCurrentController().getViewCursor()
    _ = view_cursor.gotoRange(search_found, False)
    table_name = view_cursor.TextTable.TableName
    cell_name = view_cursor.Cell.CellName
    table = document.TextTables.getByName(table_name)
    cell = table.getCellByName(cell_name)

    cell_cursor = cell.createTextCursorByRange(search_found)
    cell.Text.insertTextContent(cell_cursor, new_reference_mark, True)

    elif search_found.getText().supportsService("com.sun.star.text.Text"):
    if search_found.getText().supportsService("com.sun.star.text.TextFrame"):
    view_cursor = document.getCurrentController().getViewCursor()
    _ = view_cursor.gotoRange(search_found, False)
    frame_name = view_cursor.TextFrame.Name
    frame = document.TextFrames.getByName(frame_name)
    frame_cursor = frame.createTextCursorByRange(search_found)
    frame.Text.insertTextContent(frame_cursor, new_reference_mark, True)

    elif search_found.getText().supportsService("com.sun.star.text.Endnote"):
    search_found_start = search_found.getStart()
    endnotes = document.getEndnotes()
    for i in range (endnotes.Count):
    endnotes_found_start = endnotes.getByIndex(i).Start

    try:
    _ = endnotes.getByIndex(i).Text.compareRegionStarts(endnotes_found_start,search_found_start)
    sucess = i
    except:
    pass

    required_endnote = endnotes.getByIndex(sucess)
    endnote_cursor = required_endnote.createTextCursorByRange(search_found)
    required_endnote.Text.insertTextContent(endnote_cursor, new_reference_mark, True)

    elif search_found.getText().supportsService("com.sun.star.text.Footnote") \
    and not search_found.getText().supportsService("com.sun.star.text.Endnote"):
    search_found_start = search_found.getStart()
    footnotes = document.getFootnotes()
    for i in range (footnotes.Count):
    footnotes_found_start = footnotes.getByIndex(i).Start
    try:
    _ = footnotes.getByIndex(i).Text.compareRegionStarts(footnotes_found_start,search_found_start)
    sucess = i
    except:
    pass

    required_footnote = footnotes.getByIndex(sucess)
    footnote_cursor = required_footnote.createTextCursorByRange(search_found)
    required_footnote.Text.insertTextContent(footnote_cursor, new_reference_mark, True)

    else:
    document.Text.insertTextContent(search_found, new_reference_mark, True)


    search_found = document.findNext(search_found, search_descriptor)

  • Thank you, @gwyn-hopkins! I also happened to stumble across the fact that the field codes apparently get exposed in a copy-and-pasteable format if we click the
    "Switch to a Different Word Processor …" button (in, say, a copy of the document we're actually working in). Combined with step 7 from your workflow above, this might also be a way of condensing steps 1–6 if one wanted to go with that workflow.

    Thanks, again, for having a look.
  • @adomasven I don't really follow where you are going with this discussion now but it would be great if someone could contribute a fix to LibreOffice for this bug.
    In the meantime I have discovered a rather clumsy workaround. I installed OpenOffice, copied my whole (long) document to an OpenOffice Writer document and from there I was able to copy back (and hence successfully move) large sections of my original document while retaining the Zotero citation links.
  • edited February 19, 2024
    We are not in a position to submit a fix in LibreOffice for this. The LibreOffice codebase is very large and complicated, and we have plenty of important bugs and features for Zotero to work on. Moreover, recently someone submitted a 2-line bugfix for an issue that affects Zotero and it took a few months to finally pass tests, and then it eventually had to be reverted because it broke some other feature.
    In the meantime I have discovered a rather clumsy workaround. I installed OpenOffice, copied my whole (long) document to an OpenOffice Writer document and from there I was able to copy back (and hence successfully move) large sections of my original document while retaining the Zotero citation links.
    Are you sure this doesn't work by copying into a different document, and then back into the original one using the regular LibreOffice?
  • For me, pasting into a new LibreOffice document and then back to the original broke Zotero citation links. I did try that first. :)
    OpenOffice is considered the more stable of the two, but without rapid development. I guess it has fewer bugs.
    Sometimes I wish I had stuck with org-mode :-\
    BTW thanks for your great work on Zotero.
  • OpenOffice may be more stable for some operations, but it is also discontinued since 2011 and hence why not supported by Zotero. In this case I'm not sure it's a matter of stability either way.
  • I see that OpenOffice.org was taken over by the Apache Software Foundation and the suite is now officially Apache OpenOffice. It seems that it has had only minor enhancements since then but has new releases every 3 months or so, mainly with security and bug fixes - 19 so far. The latest version is 4.1.15. It has an open software license and seems to work well with Zotero.
  • Oh, I didn't even realize this. It seems that the current Apache OpenOffice is actually a fork of NeoOffice https://en.wikipedia.org/wiki/Apache_OpenOffice . We mostly discontinued official support for OpenOffice as we considered it to be itself discontinued, which is still largely the case. The only actively developed branch of OpenOffice and the highest user-base one as it comes preinstalled with most versions of Linux is LibreOffice, so we only really recommend it, but we are aware that technically our extension works with other forks of OpenOffice, although it might stop at any point in the future as we don't test with other forks.
  • A fork of StarOffice, I think. Apart from lack of development, the main issue with OpenOffice seems to be lack of transparency regarding timeliness of security fixes.
    LibreOffice plus Zotero is excellent for me except for the copy and paste issue.
    Also, if I was able to use the Master Documents and sub-documents with Zotero, that would be great. But it seems they don't work together. Not a biggie.
    I do like the innovation to have Zotero support installed automatically on supported word processors, making it more accessible.
Sign In or Register to comment.