training_man: 27.0.1+2494687 writes a non-zero block trailer, training/mentoring readers fail closed

Open
#82 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
1-2 days
Newbie friendliness
49/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
python
Domain
backend, cli

Research direction

Start with _skip_block_trailer in readers/training.py and the contributing guide’s rule for blocking versus advisory checks. Compare the training and mentoring readers against saves with and without mentoring groups; the issue reports the trailer values and that relaxing the assertion lets all gates pass. Done means both readers handle the reported FM27 build while preserving integrity checks and surfacing the unknown word appropriately.

Written by the indexing model from the issue text.

Description

What went wrong

save.training() and save.mentoring() both fail closed on saves from FM27 build 27.0.1+2494687:

UnsupportedGameError: training blocks whose trailer is not all zero are not supported by this layout

The failure is _skip_block_trailer in readers/training.py: the four bytes after a team block's mentoring groups are no longer all zero on this build.

What I found (own saves + the in-game UI)

  • The training_man section schema is unchanged (32), so the 27.0.0+2486695 layout is borrowed as expected, and everything else in the walk still decodes: one block per team of the managed club, weekly records stepping exactly seven days across the whole calendar, mentoring group member selectors resolving to player records.
  • Only blocks that hold mentoring groups carry the non-zero word:
    • blocks without groups (the youth and B sides in my club's section): trailer still 00 00 00 00, followed by the terminator byte as before;
    • the first-team block with 3 mentoring groups: 05 00 00 00 (u32 LE = 5) then the terminator;
    • save-diff against a single in-game event: after creating a 4th mentoring group in the game and saving, the word became 06 00 00 00, and the new group was stored under group number 5 while groups 1-3 exist (no group number 4 anywhere in the section) - so the word may be a group-allocation counter. That is a guess from two data points; I have not decoded it.
  • With the all-zero assertion relaxed locally (accepting and recording the word, changing nothing else), the full walk and every gate bound pass, which suggests a reserved word now written by the game rather than a wider layout shift.

What I expected

By the contributing guide's own rule - a blocking check needs an integrity condition, population assumptions belong in advisory checks - the all-zero trailer assertion looks like a population assumption about reserved bytes that 27.0.1 now breaks in normal play. Recording the raw word in a warning instead of raising would keep both readers usable on this build while flagging the unknown content. Careers with no mentoring groups set up should read fine (their blocks keep zero trailers).

Environment

  • fmsave version: 0.11.0
  • Python: 3.14.7
  • OS: macOS
  • Game build: 27.0.1+2494687 (known_build: false, borrows the FM27 27.0.0 layouts)

fmsave validate SAVE --json output (trimmed to the relevant readers)

"section_schemas": { "training_man": 32 },
"readers": [
  { "reader": "training",  "status": "error", "record_count": null, "gates": [], "coverage": {}, "anomalies": {} },
  { "reader": "mentoring", "status": "error", "record_count": null, "gates": [], "coverage": {}, "anomalies": {} }
]

All other readers report ok. Happy to send the save privately if useful, or to run any extra probe on it.

Dominant language
Python
Stars
28
Forks
8
Avg merge
42m
Merged PRs (30d)
33

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rhiever/fmsave

All issues in rhiever/fmsave

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.