| Previous | Next |
| hrTooManyKeys | hrReadVerifyFailure |
hrRecordDeleted
Locate the failure in the Jet call chain
For hrRecordDeleted, the useful clue is the engine object that rejected the operation and the state it had reached. The decisive boundary is the cursor refers to a row that was deleted after it became the current record.
This result is the legacy Directory Service backup/restore HRESULT form of the ESE condition normally written as JET_errRecordDeleted. Preserve the original value 0xC80003F9 when a wrapper also exposes a signed JET_ERR.
The key comparison for this HRESULT is this: hrRecordNotFound is a failed key lookup; this result describes a row that existed in the cursor lifecycle. The first useful observation is to capture transaction boundaries, cursor position, bookmark, and the session that performed the delete. This it evidence distinguishes failed lookup, lost cursor currency, deleted rows, invalid bookmarks, and prepared-update state.
The ESE objects in play
| Diagnostic layer | cursor currency, bookmarks, prepared updates, and row lifecycle |
|---|---|
| Typical API surface | JetMove, JetSeek, JetGetBookmark, JetGotoBookmark, JetPrepareUpdate, JetUpdate, and JetDelete |
| Code-specific boundary | the cursor refers to a row that was deleted after it became the current record |
| First corrective direction | reseek from a stable key or bookmark and make deletion an expected concurrency outcome |
Preparing an update creates cursor state that must be completed or cancelled deliberately., cursor currency can be invalidated by navigation, deletion, rollback, or concurrent changes.
Questions the logs must answer
A useful trace for this HRESULT should preserve the first failing operation and the state of the cursor currency, bookmarks, prepared updates, and row lifecycle.
- Code-specific observation: capture transaction boundaries, cursor position, bookmark, and the session that performed the delete.
- prepared-update mode, row version, transaction, and concurrent writer; associate it with this result rather than with a later generic exception.
- the current index, seek relation, key, range, and preceding navigation result; associate it with this result rather than with a later generic exception.
- bookmark bytes and the table/database context that produced them; associate it with it rather than with a later generic exception.
Log lengths, hashes, IDs, flags, and redacted samples where appropriate.
Response and verification
- Freeze the failing request context and record it,
0xC80003F9, the Jet API name, and the current instance/session ownership. - Verify the code-specific precondition: capture transaction boundaries, cursor position, bookmark, and the session that performed the delete.
- Apply the narrow correction: reseek from a stable key or bookmark and make deletion an expected concurrency outcome.
- Before retrying it, reconcile cursor currency, row existence, bookmark validity, and prepared-update cleanup.
- add a regression test that forces the old boundary and proves cleanup leaves no stale handles; then repeat the smallest read-only or disposable test that exercises the corrected precondition.
Developer-facing acceptance test
Build a focused test that reproduces it at the cursor currency, bookmarks, prepared updates, and row lifecycle layer. Record the precondition, execute one API call, and assert the HRESULT plus the resulting handle and transaction state. The corrected it test should change only the decisive condition—the cursor refers to a row that was deleted after it became the current record—and should prove that cleanup is safe if the call still fails.
Distinguishing signals
For this HRESULT, hrRecordNotFound is a failed key lookup; it describes a row that existed in the cursor lifecycle. The following neighboring results belong to the same broad subsystem but mark different boundaries:
hrRecordClusteredChanged | an update attempted to change a clustered key in a way the engine cannot apply in place |
|---|---|
hrRecordNotFound | a seek or lookup found no row matching the constructed key or bookmark criteria |
hrNoCurrentRecord | the cursor is before-first, after-last, on a deleted row, or otherwise not positioned on a record |
Keep it in the incident record; replacing it with “database error” hides whether the next step is handle renewal, schema correction, lock reconciliation, or file preservation.
Actions that can hide or worsen the problem
- do not reuse bookmarks after restore, rebuild, or incompatible schema change.
- do not retry a write without rereading the row and its business preconditions.
Technical references
- JetGetBookmark — used to verify the ESE object model, API ordering, or error family relevant to it.
- JetPrepareUpdate
- JetUpdate
- ESE functions
- Microsoft: JET_ERR enumeration
Looking for a different code? Search another status or error code.
