You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Portions of this content were authored by an AI agent. The agent has read AGENTS.md and the human submitter accepts responsibility for
compliance with the rules in that document.
AI-assisted (disclosure block included as described in AGENTS.md)
Current Behavior
An AlphaTex export → import round-trip fails when a note carries a fractionalharmonicValue.
AlphaTexExporter.exportToString() writes that value into the note's effect group as a decimal — e.g. {fh 2.4} — and ScoreLoader.loadAlphaTex() then rejects that same output:
AT206 Unexpected end of file. Group not closed.
AT202 Unexpected 'RBrace' token. Expected one of following: Number,String,Ident
Whole-number values are fine. Only fractional ones fail. Measured on v1.8.4, starting from a score with all other harmonics cleared so nothing else could influence the result:
harmonicType
harmonicValue
exported
re-import
Feedback (6)
(none)
—
ok
Feedback (6)
0
{fh 0}
ok
Feedback (6)
2
{fh 2}
ok
Feedback (6)
12
{fh 12}
ok
Feedback (6)
2.4
{fh 2.4}
throws
Feedback (6)
3.7
{fh 3.7}
throws
Artificial (2)
2
{ah 2}
ok
Artificial (2)
2.4
{ah 2.4}
throws
The failure does not require a file at all — appending the effect to an otherwise valid AlphaTex document reproduces it, so this is not specific to any particular score:
appended before EOF
result
1.1{fh}
ok
1.1{fh 2}
ok
1.1{fh 2.4}
throws
1.1{ah}
ok
1.1{ah 2}
ok
1.1{ah 2.4}
throws
We hit this in production: we export Guitar Pro scores to AlphaTex to serve from a song catalog, and every affected score published and listed normally but then failed to load for the client. A score whose harmonicValue is 2.4 in the source .gp is unusable as published.
Expected Behavior
Whatever AlphaTexExporter writes should be readable by ScoreLoader.loadAlphaTex — i.e. export → import should round-trip losslessly, including fractional harmonic values. A decimal literal that the exporter itself just produced should not be a parse error on the way back in.
If fractional harmonic values are not meant to be representable, the exporter should not silently emit them; either way the current pair of behaviours (emit, then reject) is not self-consistent.
Steps To Reproduce
Load any Guitar Pro file into alphaTab (ScoreLoader.loadScoreFromBytes).
On one note, set harmonicType to 6 (Feedback) or 2 (Artificial) and set harmonicValue to a fraction such as 2.4. Leave every other note's harmonic cleared.
Export: const tex = new alphaTab.exporter.AlphaTexExporter().exportToString(score, new alphaTab.Settings()).
Search the output for fh / ah — you will find the decimal you set, e.g. {fh 2.4}.
Re-import that same string: ScoreLoader.loadAlphaTex(tex, new alphaTab.Settings()).
It throws AT206 / AT202 as shown above.
Repeat with harmonicValue set to 2 instead of 2.4 and step 6 succeeds, which is how we isolated the fractional part as the trigger.
All rows in the tables above were produced against an unmodified v1.8.4 build (verified free of any local patches) on Node.js v24.18.0, macOS.
Platform
Node.js
Anything else?
We only exercised ah (Artificial) and fh (Feedback). th (Tap), ph (Pinch) and sh (Semi) appear to take the same value argument in the same note-effect group and are likely affected too, but we did not confirm that and did not want to overstate it — happy to test more if useful.
We could not construct a small standalone AlphaTex document that isolates this: the minimal forms we tried were themselves rejected before the fractional value came into play. So the reproduction above is programmatic rather than a copy-pasteable document.
We are currently working around this in our own vendored copy of v1.8.4 by accepting these values locally. We have not proposed a code change here and are happy to run any additional experiments you need — for example exporting a known-good score at several fractional values across every valued harmonic type, or checking whether the same asymmetry shows up in the .NET and Kotlin ports, since TypeScript is the source of truth for those.
Note
AI-authored disclosure (
alphatab-ai-authored-v1)Portions of this content were authored by an AI agent. The agent has read
AGENTS.md and the human submitter accepts responsibility for
compliance with the rules in that document.
Is there an existing issue for this?
I have read the contribution rules
AI authorship
AI-assisted (disclosure block included as described in AGENTS.md)
Current Behavior
An AlphaTex export → import round-trip fails when a note carries a fractional
harmonicValue.AlphaTexExporter.exportToString()writes that value into the note's effect group as a decimal — e.g.{fh 2.4}— andScoreLoader.loadAlphaTex()then rejects that same output:Whole-number values are fine. Only fractional ones fail. Measured on v1.8.4, starting from a score with all other harmonics cleared so nothing else could influence the result:
harmonicTypeharmonicValue6)6)0{fh 0}6)2{fh 2}6)12{fh 12}6)2.4{fh 2.4}6)3.7{fh 3.7}2)2{ah 2}2)2.4{ah 2.4}The failure does not require a file at all — appending the effect to an otherwise valid AlphaTex document reproduces it, so this is not specific to any particular score:
1.1{fh}1.1{fh 2}1.1{fh 2.4}1.1{ah}1.1{ah 2}1.1{ah 2.4}We hit this in production: we export Guitar Pro scores to AlphaTex to serve from a song catalog, and every affected score published and listed normally but then failed to load for the client. A score whose
harmonicValueis2.4in the source.gpis unusable as published.Expected Behavior
Whatever
AlphaTexExporterwrites should be readable byScoreLoader.loadAlphaTex— i.e. export → import should round-trip losslessly, including fractional harmonic values. A decimal literal that the exporter itself just produced should not be a parse error on the way back in.If fractional harmonic values are not meant to be representable, the exporter should not silently emit them; either way the current pair of behaviours (emit, then reject) is not self-consistent.
Steps To Reproduce
ScoreLoader.loadScoreFromBytes).harmonicTypeto6(Feedback) or2(Artificial) and setharmonicValueto a fraction such as2.4. Leave every other note's harmonic cleared.const tex = new alphaTab.exporter.AlphaTexExporter().exportToString(score, new alphaTab.Settings()).fh/ah— you will find the decimal you set, e.g.{fh 2.4}.ScoreLoader.loadAlphaTex(tex, new alphaTab.Settings()).AT206/AT202as shown above.Repeat with
harmonicValueset to2instead of2.4and step 6 succeeds, which is how we isolated the fractional part as the trigger.Version and Environment
All rows in the tables above were produced against an unmodified v1.8.4 build (verified free of any local patches) on Node.js v24.18.0, macOS.
Platform
Node.js
Anything else?
ah(Artificial) andfh(Feedback).th(Tap),ph(Pinch) andsh(Semi) appear to take the same value argument in the same note-effect group and are likely affected too, but we did not confirm that and did not want to overstate it — happy to test more if useful.