Summary
A book in which every sheet transcribes successfully can still export nothing. During
Book.export, reloading a sheet's persisted structure throws
NullPointerException: Cannot read the array length because "this.sequences" is null from
RunTable.afterUnmarshal. The recovery path then fails too, because reopening the book's
zip filesystem throws FileSystemAlreadyExistsException. The null sheet finally surfaces
as an NPE in Voices.refineScore, and no MusicXML is produced.
Two separate defects are visible in the one trace, and I think the second is worth fixing
independently of the first: the fallback that exists to rescue this situation cannot work.
Environment
Audiveris 5.11.0, build 9e1e55cd2746037d059345881c53e6a6754bffbd
Windows 11 10.0, amd64
OpenJDK 64-Bit Server VM (build 25.0.3+9-LTS, mixed mode)
Tesseract OCR 5.5.2
Minimal reproducer
Haydn, Symphony No. 45 "Farewell", Timothy Lanfear 2020 engraving — freely downloadable
from IMSLP as file #633504:
https://imslp.org/wiki/Symphony_No.45_in_F-sharp_minor,_Hob.I:45_(Haydn,_Joseph)
Take pages 3–9 only (page 1–2 are front matter) into a new PDF and run:
Audiveris.exe -batch -export -save -output <dir> -- haydn-pages-3-9.pdf
All 7 sheets reach PAGE. Exit code 1, no MusicXML.
I bisected this:
| pages |
sheets reaching PAGE |
export |
| 3–7 |
5 of 5 |
succeeds |
| 3–8 |
6 of 6 |
succeeds |
| 3–9 |
7 of 7 |
fails |
| 9 alone |
1 of 1 |
succeeds |
So page 9 triggers it only in combination with the preceding sheets, not on its own. Page 9
is the first in the book whose systems hold three different staff counts (book.xml gives
<part> counts per <system> of 4, 5 and 6 on that sheet); pages 3–7 are uniformly 6 and
page 8 has two distinct counts.
Actual
Sheets 1–6 reload, sheet 7 does not:
INFO SheetStub.java:1000 | Loaded /sheet#1 ... Loaded /sheet#6
WARN SheetStub.java:1002 | Error in loading sheet structure javax.xml.bind.UnmarshalException
javax.xml.bind.UnmarshalException: null
at com.sun.xml.bind.v2.runtime.JaxBeanInfo.invokeUnmarshallCallback(JaxBeanInfo.java:571)
at com.sun.xml.bind.v2.runtime.JaxBeanInfo.invokeAfterUnmarshalMethod(JaxBeanInfo.java:562)
Caused by: java.lang.NullPointerException: Cannot read the array length because "this.sequences" is null
at org.audiveris.omr.run.RunTable.afterMarshal(RunTable.java:339)
at org.audiveris.omr.run.RunTable.afterUnmarshal(RunTable.java:359)
Audiveris then tries to recover, and the recovery itself fails:
INFO SheetStub.java:1003 | Trying to restart from binary
WARN DataHolder.java:166 | Error reading data from BINARY.png
java.nio.file.FileSystemAlreadyExistsException: null
at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.newFileSystem(Unknown Source)
at org.audiveris.omr.util.ZipFileSystem.open(ZipFileSystem.java:111)
at org.audiveris.omr.sheet.Book.openBookFile(Book.java:1840)
at org.audiveris.omr.sheet.Book.openSheetFolder(Book.java:1856)
at org.audiveris.omr.sheet.DataHolder.getData(DataHolder.java:143)
at org.audiveris.omr.sheet.SheetStub.grabBinaryTable(SheetStub.java:1101)
at org.audiveris.omr.sheet.SheetStub.resetToBinary(SheetStub.java:1471)
at org.audiveris.omr.sheet.SheetStub.getSheet(SheetStub.java:1004)
at org.audiveris.omr.score.Score.getPage(Score.java:483)
Leaving a null sheet, which surfaces as:
WARN CLI.java:956 | Exception occurred java.lang.NullPointerException:
Cannot invoke "org.audiveris.omr.sheet.Sheet.getPages()" because "sheet" is null
at org.audiveris.omr.score.Score.getPage(Score.java:485)
at org.audiveris.omr.score.Score.getPages(Score.java:621)
at org.audiveris.omr.sheet.rhythm.Voices.refineScore(Voices.java:343)
at org.audiveris.omr.sheet.Book.reduceScores(Book.java:2101)
at org.audiveris.omr.sheet.Book.transcribe(Book.java:2633)
at org.audiveris.omr.sheet.Book.export(Book.java:593)
Expected
A book whose sheets all reached PAGE should export.
Notes
RunTable.afterUnmarshal (line 359) calls afterMarshal (line 339), which dereferences
sequences. On this sheet sequences is null after unmarshalling — an empty or
run-less RunTable is my guess, but I have not read the source.
- The
FileSystemAlreadyExistsException looks independently fixable: ZipFileSystem.open
is asked for a filesystem on a book file that is already open at that moment, so
resetToBinary can never succeed on a book being exported. Even if (1) is fixed,
anything else that triggers resetToBinary mid-export will hit this.
I also see the getPages() NPE at a different sheet index depending on how many sheets
are in the book, over overlapping content, so I would not read too much into which sheet is
named in any single run.
Filed separately: a RHYTHMS-step NPE in Voices.refineSystem on the same score's later
pages.
Summary
A book in which every sheet transcribes successfully can still export nothing. During
Book.export, reloading a sheet's persisted structure throwsNullPointerException: Cannot read the array length because "this.sequences" is nullfromRunTable.afterUnmarshal. The recovery path then fails too, because reopening the book'szip filesystem throws
FileSystemAlreadyExistsException. The null sheet finally surfacesas an NPE in
Voices.refineScore, and no MusicXML is produced.Two separate defects are visible in the one trace, and I think the second is worth fixing
independently of the first: the fallback that exists to rescue this situation cannot work.
Environment
Minimal reproducer
Haydn, Symphony No. 45 "Farewell", Timothy Lanfear 2020 engraving — freely downloadable
from IMSLP as file #633504:
https://imslp.org/wiki/Symphony_No.45_in_F-sharp_minor,_Hob.I:45_(Haydn,_Joseph)
Take pages 3–9 only (page 1–2 are front matter) into a new PDF and run:
All 7 sheets reach
PAGE. Exit code 1, no MusicXML.I bisected this:
So page 9 triggers it only in combination with the preceding sheets, not on its own. Page 9
is the first in the book whose systems hold three different staff counts (
book.xmlgives<part>counts per<system>of 4, 5 and 6 on that sheet); pages 3–7 are uniformly 6 andpage 8 has two distinct counts.
Actual
Sheets 1–6 reload, sheet 7 does not:
Audiveris then tries to recover, and the recovery itself fails:
Leaving a null sheet, which surfaces as:
Expected
A book whose sheets all reached
PAGEshould export.Notes
RunTable.afterUnmarshal(line 359) callsafterMarshal(line 339), which dereferencessequences. On this sheetsequencesis null after unmarshalling — an empty orrun-less
RunTableis my guess, but I have not read the source.FileSystemAlreadyExistsExceptionlooks independently fixable:ZipFileSystem.openis asked for a filesystem on a book file that is already open at that moment, so
resetToBinarycan never succeed on a book being exported. Even if (1) is fixed,anything else that triggers
resetToBinarymid-export will hit this.I also see the
getPages()NPE at a different sheet index depending on how many sheetsare in the book, over overlapping content, so I would not read too much into which sheet is
named in any single run.
Filed separately: a
RHYTHMS-step NPE inVoices.refineSystemon the same score's laterpages.