Skip to content

BE: PGN import rejects compact move-number format (1.e4) with a false "Illegal move" #945

Description

@abdulwaarith0

Bug

backend/modules/chess/src/pgn.rsparse_moves() strips move numbers with the regex ^\d+\.+$, which only matches when the move number is its own whitespace-separated token (the spaced form 1. e4).

A compact but perfectly valid PGN where the move number is glued to the move — 1.e4 e5 2.Nf3 Nc6, the form produced by many exporters/engines — tokenizes to ["1.e4", "e5", "2.Nf3", "Nc6"]. The 1.e4 / 2.Nf3 tokens slip through the filter and are then handed to the SAN parser, which rejects them.

Impact

This is live via the JWT-authenticated POST /games/import endpoint (backend/modules/api/src/games.rs:396). Importing a compact-format PGN fails with a 422 "Illegal move" even though the game is completely legal.

Reproduce

[White "A"]
[Black "B"]
[Result "*"]

1.e4 e5 2.Nf3 Nc6 *
  • Compact 1.e4 e5 2.Nf3 Nc6 → parsed ["1.e4","e5","2.Nf3","Nc6"]validate_game = false
  • Spaced 1. e4 e5 2. Nf3 Nc6 → parsed ["e4","e5","Nf3","Nc6"]validate_game = true

Suggested fix

Strip a leading move-number prefix from each token (^\d+\.+, no trailing $ anchor) instead of dropping whole-number-only tokens. This handles 1.e4, 1. e4, 1...e5, and 10.Ba2 uniformly.

Related

While here, parse_moves only removes non-nested variations (\([^()]*\)), so nested variations like (1. d4 (2. c4) Nf6) leave the outer parentheses behind. Noting for a possible follow-up; not addressed here.

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave program

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions