Repair Corrupted MS Access Database — Field Recovery Protocol (ACCDB & MDB)

A calm, ordered recovery sequence for IT leads and power users — not a panic click through Compact and Repair. Covers ACCDB (ACE engine) and MDB (JET engine), VBA p-code faults, error codes 3049 / 3800 / 9505, MSysCompactErrors, DAO/ADO row rescue, and the boundary where DIY ends and Professional Repair Services begin.

Error 3049

Unrecognized database format

Header / version damage → Tier 3

Error 9505

Database in inconsistent state

Engine inconsistency → Tier 2 + MSysCompactErrors

Error 3800

'Id' is not an index in this table

Catalog index fault → Tier 3 object surgery

Stop the bleed — do this before any repair attempt

Treat the damaged file like forensic evidence: read-only mount where possible, no in-place writes, and a written log of every tool run and its outcome. Organizations that recover cleanly are the ones that preserved their binary optionsbefore optimism did further damage — not the ones that ran Compact & Repair five times hoping for a different result.

Identifying corruption type: error codes and symptoms

The most important diagnostic split is VBA / compiled p-code damage versus ACE/JET engine and table-storage damage. They require different tools. Using the wrong one wastes time and can widen the failure.

VBA / p-code corruption — symptoms

  • Compile errors despite tables opening and data reading correctly
  • Ghost procedures — the editor shows a procedure that no longer exists in module text
  • Missing breakpoints that were previously saved
  • Crashes on compile that do not reproduce on another machine after a decompile
  • References resolving differently per workstation (library path divergence)

→ Start at Tier 1: /decompile. The compiled stream diverged from source text; discarding p-code forces a clean recompile from module source.

ACE/JET engine / table-storage damage — error codes

  • Error 3049 — "Cannot open database 'filename.mdb'. It may not be a database that your application recognizes, or the file may be corrupt." Causes: version mismatch (ACCDB opened in pre-2007 Access), incomplete file transfer, or severe page-header damage. Verify file size and Office bitness before assuming corruption.
  • Error 9505 — "Microsoft Access has detected that this database is in an inconsistent state and will attempt to recover the database." Access will auto-compact and log failures in MSysCompactErrors. Review that table before discarding the repaired copy — it names every object that failed.
  • Error 3800 — "'Id' is not an index in this table" (also seen as 'AOIndex is not an index in this table'). The engine found an index reference in the catalog pointing at a definition that no longer exists — classic interrupted-write symptom. Expect table-level object surgery via new-container import; a single Compact will not fix this.
  • Error 3011 — "The Microsoft Jet database engine could not find the object 'ObjectName'." System table reference broken; often follows a partially completed schema change or compact that stopped mid-write.
  • "Not a valid bookmark" — row-level pointer corruption, often in tables with heavy Long Text / Memo churn or after a network drop during a record save.

→ Engine errors that reproduce across multiple machines point to catalog/page damage. Skip /decompile; go to Tier 2 (Compact) or Tier 3 (new-container import).

Step-by-step recovery tiers (execute in order, on copies)

Each tier is a separate experiment on a copy of the previous best artifact. If a tier partially opens the world, snapshot that win before advancing. Document row counts after every step so you can prove recovery completeness to finance or operations.

Tier 1 — /decompile (strip corrupt p-code from VBA stream)

Launch MSACCESS.EXE with the /decompile command-line switch against a disposable copy of the front-end (or the monolith if you have not split). The engine discards all compiled artifacts and forces a full recompile from stored module text. This resolves corruption in the compiled stream without touching table data.

  1. Close all Access instances on all machines.
  2. From Win+R, paste and adjust: "C:\Program Files\Microsoft Office\root\Office16\MSACCESS.EXE" /decompile "C:\Recovery\copy_FE.accdb"Match the MSACCESS.EXE path to your Office version and bitness (Office16 = 2016/2019/2021/365, 32-bit path differs).
  3. After Access opens the file, immediately open the VBA Editor (Alt+F11).
  4. Click Debug → Compile [ProjectName]. Fix any reference errors (Tools → References).
  5. Save (Ctrl+S). Now compact this copy only via File → Info → Compact & Repair.
  6. Test all critical forms and reports before promoting to production.

If /decompile crashes immediately: the damage is outside p-code — forms binary stream or table storage. Do not loop decompile. Advance to Tier 2.

Tier 2 — Compact & Repair with MSysCompactErrors review

Compact & Repair reclaims disk space, rebuilds page maps, and re-indexes internal structures. It is effective for bloat-related degradation and minor engine inconsistencies. It is dangerous run on severe page-header damage — it can compact a partially-wrong file into a smaller, still-wrong file with fewer recovery options remaining.

  1. Make a fresh copy of the corrupt file. Open the copy in Access with exclusive access (no other users).
  2. Go to File → Info → Compact & Repair Database. If Access prompted you on open (Error 9505), select Yes — but only on a copy.
  3. After completion, check for the MSysCompactErrors system table: right-click the Navigation pane header → Navigation Options → check Show System Objects. If MSysCompactErrors exists, open it — it lists every object Access could not repair by name. Those are your Tier 3 targets.
  4. Test data in key tables. Run row counts against a known backup or export.

If Compact completes but MSysCompactErrors lists objects, or if Compact fails or loops, the file has engine-level structural damage. Advance to Tier 3.

Tier 3 — New container import (object isolation)

The professional pattern: create a blank database and import objects one class at a time. When an import fails, you have named the corruption carrier without dragging the entire damaged catalog forward. The file container is often damaged while most objects are salvageable.

Step 1

Create a blank database in the same engine family

ACCDB for ACE (Access 2007+), MDB for JET (Access 2003 and earlier). Match Office bitness. Do not set a password yet — it complicates import passes.

Step 2

Import tables — validate before continuing

External Data → Import & Link → Access. Import tables in batches of 5–10. After each batch, run SELECT COUNT(*) FROM [TableName] and compare to your last known export or backup count. A table that fails import is a corruption carrier — log it, note the error message, and move on. You can attempt DAO rescue on it later (Tier 4).

Step 3

Import queries, then forms and reports

Queries depend on tables — import them next. Forms and reports last so control sources resolve. If a form import fails, create a blank form in the new container and manually copy controls from the damaged form one by one to bisect which control holds the damaged stream.

Step 4

Import modules — fix references — /decompile if needed

Import standard and class modules last. If compile errors appear, fix library references (Tools → References in VBA Editor) before editing code. If p-code is still suspect after import, run /decompile on this new container before promoting.

Step 5

Recreate relationships and test referential integrity

Relationships do not always import correctly. Recreate primary keys and foreign key enforcement manually. Run append/delete probes on non-production records to confirm the catalog matches your business rules before cutting over.

This sequence is the machine-readable HowTo embedded in this page's structured data. After tables land and counts validate, you have a defensible partial recovery even if some objects never import — which is a better position than another failed Compact on the original.

Tier 4 — DAO/ADO row rescue (bypass the UI for damaged tables)

When a table will not import through Access's UI but the engine can still open the file in some form, DAO or ADO recordsets can cherry-pick good rows field by field, bypassing the damaged area that the import wizard cannot navigate. This is slower but can recover data that the UI abandons.

  1. Open a small VBA module in a healthy Access database (not the corrupted one). Open the corrupt file as a second database via DAO: Dim dbCorrupt As DAO.Database Set dbCorrupt = DBEngine.OpenDatabase("C:\Recovery\copy_corrupt.accdb")
  2. Open a recordset on the damaged table. Wrap the read loop in error handling so a bad row logs its primary key and continues — do not let one corrupted record abort the full extraction:Dim rs As DAO.Recordset Set rs = dbCorrupt.OpenRecordset("SELECT * FROM [DamagedTable]", dbOpenSnapshot) Do While Not rs.EOF On Error Resume Next '... write rs.Fields(n).Value to new table ... On Error GoTo 0 rs.MoveNext Loop
  3. Log every skipped row's primary key. Report partial row loss to stakeholders before cutover — "we recovered 14,203 of 14,210 rows, 7 rows unreadable" is a honest recovery, not a failed one.
  4. Strip indexes and relationships from the damaged table before attempting DAO reads if the engine refuses the table outright — index structures are frequent corruption carriers and their absence lets the engine read raw row data.

Exporting partial data to CSV or Excel and re-importing into the new container is also valid at this tier. Losing one corrupted record is always better than losing an entire table.

Tier 5 — JetComp.exe (legacy JET / MDB compaction)

JetComp.exe is the standalone JET compact utility — most relevant for .mdb workflows where you need a batchable, scriptable compact outside of the Access UI. It is not a silver bullet for .accdb files; modern ACCDB repair paths use Access itself or specialized binary tooling after proper triage.

Use JetComp when you have a defensible MDB copy, suspect bloat or structural slack, and want a compact that logs to a file rather than flashing a dialog. Always pair with validation queries afterward — JetComp will compact some forms of inconsistency into a smaller, still-incorrect file without warning.

For ACCDB workloads: new-container import (Tier 3) followed by ACE compact on the validated new container is the safer path. The rule is the same: prove the object set is sound before you compact anything.

Why MS Access databases corrupt — root causes

Corruption is almost never random. ACE and JET both assume stable block I/O: when the OS reports a successful write but the storage layer reorders or truncates the data, the engine's internal linked lists for tables, indexes, and long-value chains fall out of sync. That class of fault rarely self-heals.

The most common environmental triggers in production:

  • Wi-Fi or VPN drops mid-transaction. Access holds write locks across multiple page writes. A network interruption mid-sequence leaves the file in a partial state with no rollback — exactly Error 9505.
  • Power loss without UPS. Same mechanism, hardware-caused. Any open write at the moment of shutdown is partially committed.
  • Cloud sync tools — OneDrive, Dropbox, SharePoint. Sync clients interleave their own writes with user saves. Access expects stable block I/O; sync agents are not a database SAN. Keep live backends entirely off sync folders.
  • Anti-virus scanning the live .laccdb lock file. AV scanners can hold a read lock on the lock file during peak edits, which causes Access to mis-detect a stale lock and take corrective action against an active session.
  • Unsplit monolithic file with multiple concurrent writers. The JET/ACE engine was designed for a split front-end/back-end model. Multi-user writes directly against a single shared .accdb file on a marginal SMB path are the most reliable way to produce repeat corruption.
  • Oversized Long Text / Memo fields with high churn. Long-value chains are a known structural weak point. Wide tables with frequently updated Memo fields accumulate LV chain fragmentation that compounds compaction risk over time.
  • Laptops sleeping with open database handles. Hibernate while a .accdb is open leaves a stale lock file and can interrupt a background write Access was completing.

If the same database keeps corrupting after repair, you do not need another repair cycle — you need a post-incident review that names the write pattern, network path, and hardware facts and changes them. Repeat heroics without root-cause fixes are just budget spend.

Access database corruption prevention checklist

  • Split front-end / back-end. Users run local FE copies linked to a shared BE — no direct multi-user writes to the same file.
  • Wired storage for the backend. Put the .accdb BE on a wired-Ethernet NAS or file server, not Wi-Fi or a consumer sync folder.
  • UPS on the server. Protects against the most catastrophic mid-write power failures.
  • Exclude .laccdb and .ldb from anti-virus real-time scanning. AV exemptions for lock files are standard practice for Access deployments.
  • Auto compact on close — selectively. Useful for FE files users run locally; risky on shared BEs where auto-compact can trigger during active sessions.
  • Archive Long Text churn. Move historical Memo/Long Text data to archive tables; compact periodically to rebuild LV chains before they fragment.
  • Scheduled backup with open-session discipline. Backup tools that copy open .accdb files can produce inconsistent backups. Use a backup window or Shadow Copy Service aware tooling.
  • Harden VBA error paths. Unhandled errors that crash mid-write leave the engine in a partial-commit state. Every database-write subroutine needs an error handler that closes the recordset cleanly.

Page-level damage, binary triage, and when to call a specialist

Some failures are below the object layer. When binary corruption breaks page headers, scrambles long-value (LV) chains, or leaves the catalog's MSysObjects and MSysRelationshipspointing at freed storage, Access UI tools have nothing honest to latch onto. Compact & Repair loops without progress. New-container import cannot mount the system tables. Every iteration narrows the remaining recovery window.

At this tier the work is low-level inspection: comparing page structure against known-good ACCDB or MDB templates, carving recoverable row payloads from readable data pages, and making explicit business decisions about what partial restore means when referential integrity cannot be fully re-established.

If your triage ends here, stop DIY. Engage Professional Repair Services with the exact error text, file size before and after any compact attempts, and a bit-identical copy of the original. Our staged recovery process is built for production databases where "mostly works" is not an acceptable release criterion.

FAQ — Repair corrupted MS Access database

Can a corrupted MS Access database be repaired?

Yes, in most cases — when you classify the damage (VBA vs engine storage) and apply the correct tier on a preserved copy. Some page-level damage requires specialist binary recovery; honest triage identifies the ceiling early rather than after a compact destroys remaining options.

What does 'Microsoft Access has detected that this database is in an inconsistent state' mean?

Error 9505: the engine found mismatched internal structures — typically after an interrupted write. Access will attempt auto-repair and log every object it could not fix in the MSysCompactErrors system table. Review that table before discarding anything. Work from a copy only.

How do I fix 'Unrecognized database format' (Error 3049)?

First verify: is the file complete (check file size against a recent backup)? Is the Access version compatible (ACCDB requires Access 2007+)? Does Office bitness match? If all check out and the file still will not open, the page headers are damaged — proceed to new-container import or professional binary triage.

What causes Error 3800 'Id is not an index in this table'?

An interrupted write partially updated the engine's internal catalog, leaving an index reference pointing at a definition that no longer exists. Compact & Repair will not resolve this — import the affected table into a new container, rebuild its indexes manually, and validate row counts.

Will I lose data during Access database repair?

Risk is minimized when you never run destructive passes on your only copy and you validate row counts after each tier. Some page-level damage makes partial row loss unavoidable. DAO/ADO row rescue (Tier 4) can often recover the majority of rows from tables that the UI abandons entirely.

What is the difference between /decompile and Compact and Repair?

/Decompile discards compiled p-code and forces recompile from module source — it targets VBA-layer corruption only. Compact & Repair reclaims space and rewrites structural page maps — it targets bloat and minor engine inconsistencies. Wrong tool applied to the wrong failure class wastes time and can deepen damage.

How do I know if corruption is in VBA or table storage?

Tables open and data reads correctly but compile fails → VBA / p-code stream. Start at Tier 1 (/decompile). Engine refuses the file on multiple machines, or row data returns garbage, or structural errors appear (3049, 3800, 9505) → catalog/page damage. Use new-container import (Tier 3) to isolate which objects are carriers.

Why does my Access database keep corrupting after I repair it?

Repeat corruption traces to an environmental or architectural root cause: Wi-Fi/VPN drops, power loss, cloud sync tools (OneDrive, Dropbox), AV scanning the lock file, or multi-user writes to an unsplit monolithic file. Repairing without fixing the root cause produces repeat failures. You need a post-incident review, not another repair cycle.

Can OneDrive or Dropbox cause Access database corruption?

Yes. Sync clients interleave partial writes with Access saves. ACE and JET require stable block I/O — consumer sync folders do not provide it. Keep all live Access backends off sync folders entirely. Archive-only use with controlled copy-in / copy-out is acceptable.

When does Access corruption require professional binary recovery?

When Compact & Repair loops or widens damage, and new-container import cannot mount the core system tables (MSysObjects, MSysRelationships) — standard tools have no anchor left. That is when staged binary inspection, page-carving, and explicit partial-restore decisions beat another menu click.

Related: MS Access database repair (professional service)MS Access error troubleshootingFix slow Access database performanceHire MS Access developer

Free Access Audit