---
name: feedback-mechanism-right-data-absent
description: "Lớp lỗi lặp ×6 ở SOLUTION_ERP — cơ-chế ĐÚNG nhưng thứ đi qua nó KHÔNG CÓ; UAT báo \"không chạy\" thì ĐO DỮ LIỆU trước, đừng đọc/viết code"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 85c4bae3-8755-487e-bb4b-d8d8c9135463
  modified: 2026-08-05T02:12:02.568Z
---

**"Cơ-chế đúng, thứ đi qua nó không có"** — lớp lỗi đã nổ **×6** ở repo này. Khi anh/UAT báo *"cái X không tự điền / không hiện / không bắt"*, **phép đầu tiên là ĐO DỮ LIỆU PROD**, không phải đọc code rồi suy, và tuyệt đối không phải viết code mới.

**Why:** đây là **ĐẶC-TÍNH KIẾN-TRÚC**, không phải xui: schema DÙNG CHUNG ⟂ service/seed RIÊNG per-loại ⇒ một cột thêm cho loại này mặc-định **CÂM** ở loại kia trừ khi có người nối; và cột có thật thì vẫn có thể **rỗng data**. Cả 6 ca đều **build sạch + test xanh** — không có tín-hiệu máy nào kêu. Nguy nhất: viết code auto-fill "mới" khi code cũ **đã đúng và đang chạy** ⇒ tốn công, đẻ trùng-lặp, mà triệu-chứng y nguyên vì bảng vẫn rỗng.

**6 ca (ca 6 = chiều MỚI: bug do NGƯỜI DÙNG báo, fix ngây-thơ sẽ nhân đôi code đã đúng):**
1. policy tồn tại / 11-trên-13 vai `CanDelete=0`
2. endpoint PUT sống / 0 dây FE gọi
3. policy chặn đúng approver cần dùng
4. DTO thiếu field FE đang đọc
5. PMH role `Procurement` bị 403 ở b.13/b.17 (cơ-chế phân quyền đúng, vai đi qua không có quyền)
6. **@S157 PE "Địa điểm không tự lấy"** — auto-fill `Project.Location` đã wire từ S59 và **chạy đúng cả 4 tầng** (DB cột → `ProjectFeatures.cs:51` projection → FE type → `onChange` SearchableSelect); ô trống vì **prod 57/62 dự án `Location = NULL`** (chỉ 5 dự án có địa chỉ — đúng 5 dòng có địa chỉ trong Excel nhập S55).
7. 🔄 **@S172 CHIỀU NGƯỢC — dữ-liệu CÓ, người ĐO tra nhầm sổ.** `cicd-monitor` thử `nv.test@…` → 401 ×2 ⇒ kết **"credential UAT chết trên prod ⇒ chân non-admin KHÔNG ĐO ĐƯỢC"**, bỏ ngỏ gotcha #85. Thật ra bộ user test đang sống nằm ở `docs/HANDOFF.md` slot (64) (`test.drafter@`/`test.approver@`, password đổi theo policy prod ≥12 ký-tự); lead đo lại → login 200/200, và chân đó **đóng sạch**. ⇒ Không phải cơ-chế hỏng, cũng không phải data rỗng, mà là **phép đo trỏ sai nguồn**.

**How to apply:**
- UAT báo "không chạy" ⇒ **sqlcmd đếm dữ liệu prod TRƯỚC** (`SELECT COUNT(*), SUM(CASE WHEN <col> IS NULL...)`). Một câu query rẻ hơn một vòng đọc code + một lần sửa nhầm.
- Rồi mới truy dây theo tầng: DB cột → DTO projection → FE type → chỗ tiêu-thụ. Đủ 4 tầng mới kết luận "wire hỏng".
- Data rỗng ⇒ **KHÔNG sửa cơ-chế**. Hỏi owner nguồn dữ liệu; hướng anh chọn @S157 là *"để người dùng tự cập nhật Master data, cái nào không có thì không fill"* (không backfill hàng loạt).
- Vá đúng cho ca data-rỗng = **lộ LÝ DO tại chỗ** (dòng cảnh báo trỏ nơi bổ sung), vì ô trống im lặng làm người dùng tưởng hệ-thống hỏng → đẻ báo lỗi giả. Xem [[feedback-absence-looks-like-clean]].
- Báo lại cho anh phải nói thẳng *"cơ-chế không hỏng, thiếu dữ-liệu"* — đừng để anh tưởng vừa được sửa bug.
- 🔴 **"KHÔNG ĐO ĐƯỢC" là kết luận PHẢI TỰ NGHI, không phải caveat miễn phí** (ca 7). Trước khi khai nó, bắt buộc trả lời **"đã tra hết sổ có sẵn chưa?"** — `docs/HANDOFF.md` (khối chờ-anh hay giữ credential/mốc) · `docs/STATUS.md` · run-folder · session-log. Câu này **nghe như trung thực** nên trôi qua review dễ hơn một con số sai; đó chính là chỗ nguy. Cùng họ [[feedback-absence-looks-like-clean]]: vắng-mặt trông giống ổn, còn *"không đo được"* trông giống **cẩn-thận**.
- Hệ-quả cho lead khi nhận return của sub: sub khai "KHÔNG ĐO ĐƯỢC" ⇒ **đừng chép thẳng vào verdict**; tra sổ một lượt rồi mới quyết. @S172 việc này biến "6/6 + 1 chân hở" thành **7/7 chân xanh**, tốn đúng 2 lệnh curl.

Liên quan: [[feedback-root-cause-over-symptom]] (truy gốc thay vì vá triệu-chứng) · [[feedback-permission-grant-two-layers]] (cùng họ: 2 tầng độc-lập, tầng này đúng không suy ra tầng kia) · [[feedback-cardinality-change-grep-consumers]] (write-site đúng, read-site sót).
