Skip to main content
RunBook Academy

CephCXVIII · Data Integrity IncidentData Integrity Incident

When repair does not repair

Advanced⏱ ~18 mincephrados

What you'll learn

  • Confirm a requested repair actually started
  • Diagnose repairs that recur after completing
  • Recognise that repair correctly abstains on some objects
  • Verify the outcome rather than the command

Prerequisites

None — start here.

Verified against Ceph Tentacle 20.2.x · Ceph Squid 19.2.x (supported previous) · cephadm matches the verified Ceph release · podman 4.x · csi-rbd and csi-cephfs current · RBD / CephFS / RGW current (matches Ceph release) · Linux kernel 5.15+ (5.10 minimum) · Ubuntu 24.04 LTS (Ceph host baseline) · Debian 12 (Bookworm) (Ceph host baseline) · Rocky Linux / RHEL / AlmaLinux 9.x (Ceph host baseline) · Proxmox VE 9.x (cross-course integration) · Kubernetes 1.31+ (cross-course integration) · 2026-08-18

Not yet marked complete on this device.

Why this matters in production

ceph pg repair returns instantly and says nothing about what happened. Everything that matters — whether it started, whether it fixed anything, whether it will happen again — is established afterwards.

Confirming it started

ceph pg repair 12.1a4
ceph pg ls inconsistent
PG      OBJECTS  STATE                                          ACTING
12.1a4      2841  active+clean+scrubbing+deep+inconsistent+repair  [17,42,8]
Reason a repair does not startCheck
cluster scrub flags setthe flags line of ceph osd dump
the OSD is at its scrub concurrency limitceph config get osd osd_max_scrubs
the PG is not active+cleanstate includes degraded or backfilling
the primary changed after the requestre-issue against the current primary
ceph osd dump | grep -E '^flags'
ceph config get osd osd_max_scrubs
ceph status
A request against a PG whose state never gains `repair` was queued and
starved, not executed. Watch for the state, not for the command exiting.

Repairs that recur

SymptomWhat is happening
new errors, different objects, same OSDthe device is still failing
the same object again after repairthe writer is still producing bad data
errors spreading to new PGsthe fault is above the device
errors return only after recoverya bad copy is being propagated by backfill
ceph pg ls-by-osd 17 | head
ceph device ls-by-daemon osd.17
ceph log last 100 info cluster | grep -iE 'repair|inconsistent'

When repair correctly abstains

Where no copy can be selected, repair completes and leaves the object inconsistent. That is the right outcome — the alternative would be overwriting one unverified copy with another.

rados list-inconsistent-obj 12.1a4 --format=json-pretty | python3 -c '
import sys,json
d = json.load(sys.stdin)
for o in d.get("inconsistents", []):
    print(o["object"]["name"], o.get("errors"), o.get("union_shard_errors"))'

Verifying the outcome

ceph pg deep-scrub 12.1a4
# wait for the stamp to advance before believing anything
ceph pg 12.1a4 query | python3 -c '
import sys,json
print(json.load(sys.stdin)["info"]["stats"]["last_deep_scrub_stamp"])'
rados list-inconsistent-obj 12.1a4 --format=json-pretty | python3 -c '
import sys,json
print(len(json.load(sys.stdin).get("inconsistents", [])), "remaining")'
ceph health detail | grep -E 'OSD_SCRUB_ERRORS|PG_DAMAGED'

Quiz

Knowledge check · 4 questions

  1. Q1. What is the only reliable evidence that a repair fixed a PG?

  2. Q2. A repair that completes and leaves the object inconsistent means the command failed.

  3. Q3. Handle a repair that keeps recurring.

    A PG is repaired successfully on Monday. On Wednesday it is inconsistent again, with different object names, and two other PGs sharing OSD 17 have also become inconsistent.

  4. Q4. Why does automatic repair stop above an error threshold?

Passing score: 75%. Answers are checked in this browser.

Production discipline

Watch for the PG state to gain repair rather than trusting the command’s exit — a starved request looks identical to a successful one. Verify with a fresh deep scrub whose timestamp has advanced; the inconsistent-object list is the previous scrub’s cached record and will happily agree with you.

Cross-course references

  • Kubernetes: a controller accepting a spec change is not evidence the change reconciled
  • Linux: cached status output confirms a past state, not the current one