7.2 KiB
BirthBiologic — 2026-06-26 migration corruption: recovery + corrected re-migration plan
Status: PLAN (approved direction 2026-06-29 by Mike — corrected re-migration from intact Datto source; Datto 06-24 accepted as Master Donor source). Execution gated per phase.
Summary of the incident
The 2026-06-26 Datto -> SharePoint push corrupted a large set of files. Root cause is fully
diagnosed: the upload path wrote each file's byte array as space-separated DECIMAL TEXT
instead of raw binary (a "$bytes" stringification bug in the base64/stdout-capture upload
workaround used during the 06-26 session). Proof:
- Corrupt
.xlsxbegin80 75 3 4 20 0 6 0 ...= decimal of0x50 0x4B 0x03 0x04 0x14 0x00 0x06 0x00(the realPK..OOXML signature). - Corrupt
.pdfbegin37 80 68 70 ...= decimal of0x25 0x50 0x44 0x46(%PDF).
Because it operated on raw bytes, the bug is format-agnostic — .xlsx, .docx, and .pdf
were all hit, and corrupt files are inflated ~3-4x (each byte became 2-4 ASCII chars + space).
Blast radius (as of 2026-06-29, read-only probe on ACG-DWP-X-BB)
- 15 of 16 locally-cached files modified 2026-06-26 in
C:\Users\Administrator\OneDrive - Birth Biologic, LLC\are corrupt. Includes HR PII (K Steen Confidential Disclosure Agreement.pdf, Handbook Acknowledgement, Safety & Health Policy), Finance, Quality Designee docs, the Master Donor Spreadsheet, and Inventory 2025/2026. - ~3,298 additional files modified 2026-06-26 are OneDrive cloud-only (dehydrated) and were skipped to avoid mass-hydration. They are almost certainly corrupted the same way — i.e. the true scope is likely the entire 06-26 push (hundreds-to-thousands of files).
Data-loss assessment: NONE expected
- The Datto Workplace source copies are intact (
C:\Users\Public\Desktop\Datto Workplace Server Projects\), confirmed cleanPKheaders on the affected spreadsheets. - Even a corrupt file with no source is losslessly recoverable — it literally contains
the original bytes as decimal numbers; split on whitespace ->
[byte]->WriteAllBytes.
Authoritative source & path mapping
- Source of truth:
C:\Users\Public\Desktop\Datto Workplace Server Projects\(ACG-DWP-X-BB). - Target libraries:
C:\Users\Administrator\OneDrive - Birth Biologic, LLC\<Library> - Documents\(OneDrive-synced SharePoint libraries on the same host). - Mapping rule: dest
"<Folder> - Documents\..."<-> source"<Folder>\..."(strip the- Documentssuffix). Confirmed pairs: Admin, Donor Services, Supply Management (verify Quality Department + any other library before execution).
Why this method (corrected re-migration, not file repair)
The corruption is systemic to the 06-26 batch, so file-by-file repair is the wrong altitude. The clean fix exploits that both trees live on the same machine with OneDrive sync available: copy intact source files into the OneDrive library folders and let OneDrive sync them up — native, integrity-checked, no custom byte handling, no Graph chunked-upload, no RMM timeout. (SPMT is the bulk alternative; the buggy custom-script upload path is retired for this work.)
Plan
Phase 0 — Freeze & notify (do first)
- Tell client/Annise: do not open/edit/trust files in the migrated SharePoint libraries dated 2026-06-26 — they are corrupt and will be replaced.
- Pause OneDrive editing on ACG-DWP-X-BB for those libraries during the re-push to avoid sync conflicts (409s).
Phase 1 — RESULTS (completed 2026-06-29, read-only)
Method: local metadata enumeration on ACG-DWP-X-BB (size vs Datto source) + header reads;
Graph (Tenant Admin app, BirthBio tenant 19a568e8-...) for SharePoint-side spot checks.
- 3,371 files modified 2026-06-26 across the OneDrive libraries.
- 84 CONFIRMED CORRUPT (decimal-text header, not a valid signature):
- By library: Donor Services 67, Admin 12, Supply Management 3, Quality Department 2.
- By type: 59
.pdf, 20.docx, 5.xlsx. - Recovery routes: 83 RESTORE-FROM-SOURCE (clean Datto source confirmed) + 1
DECODE-OR-FIND-SOURCE (
Donor Services\Suitability\3c. Cord For Life - Donor Suitability Datto Copy.docx— no mapped source; decode the decimal-bytes or locate its source).
- ~3,197 clean (3,168 size-matched to source + 29 header-verified).
- 89 DEFERRED — cloud-only OneDrive files at
>=260-char (MAX_PATH) paths, no Datto source mapping (Quality 59, Admin 30). Unassessable by header: Graph driveItem-by-path 404s them and local[IO.File]::Openfails MAX_PATH even with\\?\+ .NET long-path switches. Must be checked/handled with a long-path-native tool (robocopy / SPMT) in execution. Lower corruption risk (no Datto source = not part of the Datto->SP byte-push) but NOT cleared.
Artifacts (committed):
2026-06-26-corruption-manifest.csv— full 3,371-row inventory (verdict, sizes, source state).2026-06-26-remediation-list.csv— the 84 corrupt files + recovery route (Phase 3 input).
Phase 1 — Full-scope inventory (READ-ONLY) [method, for reference]
- Enumerate all files (any type) modified 2026-06-26 across every OneDrive library on ACG-DWP-X-BB; classify corrupt (header != type signature / decimal-text) vs clean.
- Handle cloud-only files: either controlled batch-hydrate + header-check, or check via Graph
(Tenant Admin app,
Sites.ReadWrite.All) against the SharePoint side. - Output: authoritative corrupt-file manifest with, per file: dest path, mapped source path, source-validity (clean header? exists?), and recovery route.
Phase 2 — Pre-flight validation
- For each corrupt file confirm a clean source exists in the Datto tree (verify header).
- Partition into: A restore-from-source · B decimal-decode-recover (no clean source) · C no recovery available (investigate; expected empty).
Phase 3 — Corrected re-push (GATED — explicit go required)
- List A: copy source -> OneDrive library path (overwrite corrupt copy); let OneDrive sync. Work in batches; after each batch verify dest header flips to a valid signature.
- List B: decode decimal-text -> binary, write, verify header.
- Master Donor Spreadsheet: use Datto 2026-06-24 13:32 source (2,292,743 B) per Mike's call.
Phase 4 — Verification & reconciliation
- Re-scan libraries: confirm 0 corrupt remaining in the 06-26 set.
- Spot-open Master Donor, an Inventory, and a sample PDF to confirm they actually open.
- Reconcile file counts/sizes source vs dest. Update
wiki/clients/birth-biologic.md+ CONTEXT.
Phase 5 — Root-cause closure
- Retire the custom-script byte-capture upload path for this client. If any custom upload
remains, write binary with
[IO.File]::WriteAllBytes— never stringify a byte array. - Confirms logged in
errorlog.md(migration/datto-to-sharepoint, 2026-06-29).
Open items before execution
- Decide cloud-only handling for Phase 1 (batch-hydrate vs Graph) — Graph avoids 3,300 downloads.
- Confirm full library list + mapping (esp. Quality Department).
- Confirm no genuine 06-24->06-26 edits exist only in corrupt copies for files other than Master Donor (those would use the decimal-decode route to preserve latest content).