Summary
Deleting a taxon node clears TaxonID and PreferredTaxonID on every determination referencing that node and its descendants, and that clearing survives when the delete itself does not complete. The taxon stays in the tree; its determinations are left blank.
At UT Austin's Vertebrate Paleontology collection (VPL) this silently unlinked 10,829 determinations across 273 taxa in a single working day, during an ordinary taxon-tree cleanup session. It was not noticed for twelve months. Total confirmed impact on this instance is 8,639 determinations across two separate collections (8,631 in VPL, 8 in our non-vertebrate paleo collection over 2021–2025 — see "It is not one collection" below).
This is not related to #8064. Separate bug, separate mechanism.
Environment
- Specify 7
v7.12.0.7
- MariaDB 11.4.10
- Upgrade applied 2025-08-28 (migrations
specify.0001_initial → workbench.0008_spdataset_rolledback)
- Damage began 2025-08-29 08:50 local, the following morning
What we observed
On 2025-08-29, determination rows lost both TaxonID and PreferredTaxonID in ~70–100 discrete bursts of 15–20 rows/second spread through the working day. spauditlog for that day records:
| TableNum |
Action |
FieldName |
count |
| 9 (Determination) |
1 (update) |
taxon_id |
8,962 |
| 9 |
1 |
taxon |
29 |
| 4 (Taxon) |
2 (remove) |
(all fields) |
20 |
The 2022 rows show the failed-delete path is old — two records in four years, against 10,829 in one morning after the upgrade. Our read is that the upgrade removed a guardrail (and shipped the #5324 subtree-delete feature to this instance for the first time) rather than introducing the defect. We have instructed our collection manager to stop deleting taxon nodes entirely.
It is not one collection
We checked all nine Specify schemas on this instance with the same audit-log fingerprint (TableNum 9, FieldName taxon_id/taxon, OldValue set, NewValue empty, determination currently blank). A second collection — NPL, non-vertebrate paleontology, a separate database with a separate taxon tree — had 8 more, scattered from 2021-10-26 to 2025-11-13, all pointing at taxa that still exist. Same signature, different database, four-year span. The other seven schemas were clean.
Total repaired on this instance: 8,639 determinations across two collections.
Possibly related existing issues
Why this is severe
- Silent. No error, no warning, no count shown to the user. The determination simply goes blank.
- Undetectable by the user. A collection manager querying "current determination with empty taxon" cannot distinguish these from genuinely undetermined material.
- Unbounded. One delete attempt on a high-level node takes out every determination beneath it.
Equidae alone accounted for 2,000 records, Mammalia 766, Vertebrata 504.
- Recoverable only by luck. We recovered because auditing was enabled and we still had a monthly dump from four weeks before the incident. An institution with 30-day retention and auditing off would have lost this permanently, and would not have known for a year.
Secondary concern in the same migration
Independent of the bug above: on_delete=CASCADE on taxon.parent means deleting a family node silently deletes every genus and species beneath it. For a taxonomic tree in a collections management system that seems like a dangerous default, particularly with no user-facing confirmation of how many descendants are in scope. Same applies to geography, storage and lithostrat.
Suggested fix
- Put the reference-clearing and the delete in one atomic block, so a refused delete rolls the clearing back.
- Before clearing anything, show the user how many determinations and descendant nodes the delete will affect, and require confirmation.
- Consider refusing outright, as pre-upgrade behaviour did, when determinations reference the node.
What we can supply
spauditlog / spauditlogfield extracts for the affected window
- The full list of 273 affected taxa with per-taxon record counts
SHOW CREATE TABLE determination and the full applied-migration list with timestamps
- A pre-incident and post-incident dump of
determination for diffing
Happy to test a fix against a copy of the collection.
How we repaired it
For anyone hitting this before a fix ships. Two independent sources, reconciled before writing:
spauditlogfield.OldValue where TableNum = 9, FieldName IN ('taxon_id','taxon'), OldValue set and NewValue empty, deduplicated to the latest nulling event per determination.
- A pre-incident
mysqldump, loaded into a scratch schema and joined on DeterminationID.
The two agreed on all 8,574 records they shared, with zero conflicts. PreferredTaxonID was recomputed as COALESCE(taxon.AcceptedID, taxon.TaxonID), a rule validated against 8,574 historical values before use. Post-restore, preferred-taxon consistency across the entire determination table checks clean.
Summary
Deleting a taxon node clears
TaxonIDandPreferredTaxonIDon every determination referencing that node and its descendants, and that clearing survives when the delete itself does not complete. The taxon stays in the tree; its determinations are left blank.At UT Austin's Vertebrate Paleontology collection (VPL) this silently unlinked 10,829 determinations across 273 taxa in a single working day, during an ordinary taxon-tree cleanup session. It was not noticed for twelve months. Total confirmed impact on this instance is 8,639 determinations across two separate collections (8,631 in VPL, 8 in our non-vertebrate paleo collection over 2021–2025 — see "It is not one collection" below).
This is not related to #8064. Separate bug, separate mechanism.
Environment
v7.12.0.7specify.0001_initial→workbench.0008_spdataset_rolledback)What we observed
On 2025-08-29,
determinationrows lost bothTaxonIDandPreferredTaxonIDin ~70–100 discrete bursts of 15–20 rows/second spread through the working day.spauditlogfor that day records:The 2022 rows show the failed-delete path is old — two records in four years, against 10,829 in one morning after the upgrade. Our read is that the upgrade removed a guardrail (and shipped the #5324 subtree-delete feature to this instance for the first time) rather than introducing the defect. We have instructed our collection manager to stop deleting taxon nodes entirely.
It is not one collection
We checked all nine Specify schemas on this instance with the same audit-log fingerprint (
TableNum 9,FieldName taxon_id/taxon,OldValueset,NewValueempty, determination currently blank). A second collection — NPL, non-vertebrate paleontology, a separate database with a separate taxon tree — had 8 more, scattered from 2021-10-26 to 2025-11-13, all pointing at taxa that still exist. Same signature, different database, four-year span. The other seven schemas were clean.Total repaired on this instance: 8,639 determinations across two collections.
Possibly related existing issues
on_delete=CASCADEclass.Why this is severe
Equidaealone accounted for 2,000 records,Mammalia766,Vertebrata504.Secondary concern in the same migration
Independent of the bug above:
on_delete=CASCADEontaxon.parentmeans deleting a family node silently deletes every genus and species beneath it. For a taxonomic tree in a collections management system that seems like a dangerous default, particularly with no user-facing confirmation of how many descendants are in scope. Same applies togeography,storageandlithostrat.Suggested fix
What we can supply
spauditlog/spauditlogfieldextracts for the affected windowSHOW CREATE TABLE determinationand the full applied-migration list with timestampsdeterminationfor diffingHappy to test a fix against a copy of the collection.
How we repaired it
For anyone hitting this before a fix ships. Two independent sources, reconciled before writing:
spauditlogfield.OldValuewhereTableNum = 9,FieldName IN ('taxon_id','taxon'),OldValueset andNewValueempty, deduplicated to the latest nulling event per determination.mysqldump, loaded into a scratch schema and joined onDeterminationID.The two agreed on all 8,574 records they shared, with zero conflicts.
PreferredTaxonIDwas recomputed asCOALESCE(taxon.AcceptedID, taxon.TaxonID), a rule validated against 8,574 historical values before use. Post-restore, preferred-taxon consistency across the entiredeterminationtable checks clean.