Draft Handling
RAP / CDS / ODataadvanced

Draft Handling Part 5: Troubleshooting Draft Incidents

Key takeaway

Resolve the typical draft tickets — "document locked", "my changes disappeared", "Save does nothing", "data changed by another user" — with a symptom-based checklist and the right tools.

Explanation

📌 KEY POINTS
✅ First find the lifecycle stage: create, edit, change, prepare, activate or discard.

✅ "Locked by" is usually protection working, not a bug.

✅ "Save does nothing" is usually a Prepare/validation message the user did not see.

⚠️ Never delete draft table rows by hand — use Discard via the app or EML.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Parts 1–4 explained draft. Here is the support playbook.

SYMPTOM 1: "THE DOCUMENT IS LOCKED"
Questions:

  • Does the user see "Locked by <name>"? → another user holds the exclusive lock (active editing). Wait, or ask that user to save/discard.
  • Is the "other user" the same person on another device or browser tab? → they have their own draft; open it (Resume) or discard it.
  • Is a background job or API holding a lock? → check the job; APIs should not hold locks for long.

Tools: the lock monitor (SM12) shows current enqueue locks; draft admin data shows the draft owner.

SYMPTOM 2: "MY CHANGES DISAPPEARED"

  • Did the user click Discard/Cancel? (Check draft deletion via the app flow.)
  • Did another user take over an expired draft? Taking over discards the old draft.
  • Was the draft older than the draft lifetime and removed by the cleanup?
  • Did activation fail and the user close the page? Then the draft still exists — find it via the "Own drafts" filter.

SYMPTOM 3: "SAVE DOES NOTHING"

  • Prepare or Activate returned validation errors. Check the browser's network tab or the message popover.
  • Messages without %element or %state_area are easy to miss or stay stale.
  • An on-save determination or validation fails only at activation (not in Prepare) — check which validations are listed in Prepare.
  • Authorization or feature control rejects Activate.

Tools: ABAP Cross Trace for the request, /IWFND/ERROR_LOG, external breakpoint in the validation.

SYMPTOM 4: "DATA HAS BEEN CHANGED BY ANOTHER USER"

  • Total ETag mismatch: the active data was changed while the draft existed (often by an API or job after the lock expired). This is correct protection. The user must reload and redo the change.
  • If it happens right after the user's own actions, check that LastChangedAt/LocalLastChangedAt are maintained correctly (@Semantics) and not set manually.

━━━━━━━━━━━━━━━━━━━━
▶ SYMPTOM 5: TECHNICAL ERRORS AFTER A CHANGE

  • "Draft table does not match": fields added to the entity but draft table not regenerated.
  • Actions or associations fail only in draft: missing "with draft" on associations or missing draft actions in the projection.
  • Code works on active data but not on drafts: key fields used instead of %tky.

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP (FOR EVERY TICKET)

  1. Identify the object key and user, and the time.
  2. Determine the lifecycle stage and message text.
  3. Check draft existence and owner (the app's own-drafts filter, or a READ with %is_draft).
  4. Check locks, then messages, then ETag, then technical configuration.
  5. Fix the cause; resolve the user's draft through the app (Resume/Discard) — never by deleting table rows.

✅ CHECKPOINT: you can resolve draft tickets quickly and safely. Next topic: Service Definitions.

Code example

ABAP Code
" ===== Support helper: does a draft exist, and whose is it? =====READ ENTITIES OF zr_purchreq  ENTITY PurchaseRequest ALL FIELDS  WITH VALUE #( ( RequestUUID = uuid  %is_draft = if_abap_behv=>mk-on ) )  RESULT DATA(draft)  FAILED DATA(no_draft)." draft found     -> a draft exists (admin data: owner / last change via the app)" no_draft filled -> no draft for this object " ===== Resolve a stuck draft the RIGHT way (as the owner or with authorization) =====MODIFY ENTITIES OF zr_purchreq  ENTITY PurchaseRequest    EXECUTE Discard FROM VALUE #( ( %key-RequestUUID = uuid ) )  FAILED DATA(f) REPORTED DATA(r).COMMIT ENTITIES." NEVER: DELETE FROM zpr_head_d WHERE ...   (breaks admin data and locks) " ===== Symptom -> first check =====" "Locked by X"                 -> X is editing (exclusive lock). SM12 for locks." "Unsaved changes by X"        -> expired draft of X; take over discards it." Changes disappeared           -> discard / take-over / draft lifetime / own-drafts filter" Save does nothing             -> Prepare/Activate messages; %element/%state_area" Data changed by another user  -> total ETag: active changed meanwhile (API/job)" Draft table mismatch          -> regenerate draft table after field changes" Works active, fails in draft  -> %tky vs key; 'with draft' on associations " ===== Tools =====" ABAP Cross Trace (ADT)  - which draft actions/validations ran" /IWFND/ERROR_LOG        - OData errors" SM12                    - enqueue locks" External breakpoint     - validations during Prepare/Activate

Real project scenario

A buyer reported that request 4711 had been "locked for two days". Support first tried to delete rows from the draft table, which the team lead stopped. Following the playbook, a READ with %is_draft showed a draft owned by the buyer herself — created on her tablet. The desktop session saw it as another session's draft.
She opened the app on the tablet and discarded the draft, and the object was editable again. The team added a short note to the user guide: "Locked by yourself? Check your other devices or use the own-drafts filter".

Common mistakes

  • Deleting draft table rows manually.
  • Treating "Locked by" and total ETag messages as bugs.
  • Debugging code before checking which messages Prepare returned.
  • Forgetting that users can own drafts on other devices.
  • Not regenerating draft tables after structure changes.
  • Ignoring the lifecycle stage when analyzing.

Best practices

  • Start every ticket by identifying the lifecycle stage and message.
  • Resolve drafts through Resume/Discard, never through table deletes.
  • Make validation messages visible with %element and %state_area.
  • Keep a symptom → cause table in the support wiki.
  • Use Cross Trace, error logs and SM12 before code changes.

Interview angle

Questions: "Users say a document is locked — how do you analyze it?", "Save does nothing in a draft app — why?", "How do you clean up a stuck draft?"
Strong answer: identify lifecycle stage and message; "Locked by" means an active exclusive lock (possibly the same user on another device); "Save does nothing" is usually a Prepare/validation message not shown properly; "data changed" is a total ETag conflict. Resolve drafts via Resume/Discard with EML or the app, never by deleting draft rows. Tools: Cross Trace, /IWFND/ERROR_LOG, SM12.

Practice this lesson

Quick check

1. A request is shown as locked and support wants to delete its draft table rows. What is the correct approach?

2. Users say changing a supplier "did not save", but the draft contains the new value. What is most likely?

3. A manager's draft from Friday is activated on Monday after an API changed the same object. What prevents the old draft from overwriting the change?

Interview questions

1. A user says a purchase request has been 'locked' for two days. Support wants to delete the draft table rows. What do you do?

Answer it in your own words first, then compare.

2. After adding a field to a draft-enabled BO, activation fails and Fiori shows errors. What is the likely cause?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics