# Lessons Learned ## Bug 1: Frontend/Bulk Field Name Mismatch (2026-04-16) **现象**: 部署 API 返回 400 "invalid version",即使前端传了正确的 version **根因**: 前端发送 JSON 字段 `version`,但 DTO 只有 `Tag`(json: `tag`),handler 读 `req.Tag` 始终为空 **修复**: 在 CreateInstanceRequest 中添加 `Version` 字段,并在 Normalize() 中将 Version 复制到 Tag **How to apply**: 前后端接口字段名必须一致。DTO 的 json tag 应与前端发送的字段名匹配,或在 Normalize() 中做兼容映射 ## Bug 2: Registry Decrypt Fails with Key Mismatch (2026-04-16) **现象**: GET /registries 列表正常,但 GET /registries/{id} 返回 404 "failed to decrypt password" **根因**: 旧数据用不同 ENCRYPTION_KEY 加密,GetByID/GetByName 解密失败直接返回 error **修复**: 解密失败时返回空密码而非错误(与 List 方法行为一致) **Why**: 列表查询不触发解密(`_ = r.encryptor.Decrypt`),但单条查询需要解密。密钥不匹配不应阻断核心业务流程 **How to apply**: 涉及敏感数据解密时,对密钥不匹配的情况做 graceful fallback 而非直接报错 ## Bug 3: Docker Compose Project Conflict (2026-04-16) **现象**: 从 backend/ 目录运行 docker compose 时报错 "container name already in use" **根因**: 容器通过不同 compose 项目启动(ocdp-go vs backend),但使用了相同的容器名 **修复**: 直接用 docker 命令重启旧容器:docker stop/rm 后用 docker run 启动新镜像 **How to apply**: 当有多个 compose 文件管理同一网络时,docker run 方式更灵活 ## Bug 4: InitSchema vs Actual DB Schema Mismatch (2026-04-16) **现象**: InitSchema() 创建的 registries 表缺少 workspace_id, owner_id, is_shared 字段 **根因**: 代码中的 InitSchema 与实际 init-db.sql 不同步 **影响**: GetByID/GetByName 查询时字段数不匹配会报错 **Fix**: 修复 GetByID/GetByName 的查询和 Scan,使用实际的 DB schema **How to apply**: InitSchema() 和实际 DB schema 必须保持同步