Skip to content

fix: hash snapshots from their canonical encoding - #907

Merged
zachdaniel merged 1 commit into
ash-project:mainfrom
puyo:fix/deterministic-snapshot-hash
Oct 25, 2026
Merged

zachdaniel merged 1 commit into
ash-project:mainfrom
puyo:fix/deterministic-snapshot-hash

Conversation

@puyo

@puyo puyo commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

ash_postgres uses inspect/1 to provide the inputs to a hash function and the resulting hash is included in snapshots (presumably as a fingerprint). The problem is that inspect/1 is non-deterministic, as its output can depend on the state of the VM's atom table, causing subtle ordering changes where Map is used, hence non-deterministic hash values.

Also, the hash was computed before a merge step that normalises snapshots (e.g. those sharing a table are merged together), so it wasn't accurately using the input of the written snapshot. This PR computes it when writing instead, to fix that. The test covers this issue too, because the merge step changes the inputs to hash even in simple cases such as the setup in the test.

Existing snapshots keep working and nothing is regenerated on upgrade as nothing reads the hash back (--check and migration generation compare the snapshot fields). This isn't causing any user-facing problems today, but the value is wrong, and anything that relied on it later would be too. It is something I asked in Discord and Zach said we should fix. (general channel, 2026-10-23).

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

The snapshot hash was taken over `inspect/1` of the snapshot term. Map key
order in that output depends on the order atoms were created in the running
VM, so the same resource could hash differently between environments (e.g.
different OTP versions, dependencies or module load order). It was also
computed before the snapshot was normalised for writing, so it didn't match
the contents of the file it was stored in.

Compute it when writing instead, over the key-sorted JSON being persisted.
@zachdaniel
zachdaniel merged commit 1b0c9b2 into ash-project:main Oct 25, 2026
@zachdaniel

Copy link
Copy Markdown
Contributor

🚀 Thank you for your contribution! 🚀

@puyo
puyo deleted the fix/deterministic-snapshot-hash branch October 25, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants