# Cosmic Error Handling Guidelines

> Exception classification, rollback behavior, logging, and user prompts for Cosmic Java code.

---

## Error Categories

| Category | Use | Action |
| --- | --- | --- |
| Input validation | Missing/invalid request, form value, or parameter | Return actionable message before data mutation |
| Business rule | User action violates domain rule | Throw/return platform business exception with clear message |
| Data integrity | Missing base data, invalid relation, impossible state | Throw to rollback transaction |
| External dependency | Remote API, file service, attachment, message queue | Retry only if safe; otherwise return controlled failure |
| Platform/system | SDK/runtime unexpected failure | Log with stack trace and return generic user message |

---

## Throw vs Return

| Context | Preferred behavior |
| --- | --- |
| Inside a transaction or operation chain | Throw on any failure that would make data inconsistent |
| UI validation before operation | Return/show user-facing validation message |
| Optional side effect such as non-critical notification | Log warning and continue only if business agrees |
| External API called from a save/submit operation | Fail the operation unless explicitly designed as async compensation |

Transaction helper methods must not silently `return` after a failed validation when later writes can still commit.

---

## Java Exception Rules

- Prefer platform/business exceptions used by the target codebase, such as `KDBizException`, for business failures.
- Preserve original causes when wrapping exceptions.
- Do not throw raw `RuntimeException` for expected business branches.
- Do not call `printStackTrace()` or `System.out.println()` in production code.
- Do not expose SQL, table names, stack traces, or internal class names in user-facing messages.

---

## Logging Rules

| Situation | Level | Message content |
| --- | --- | --- |
| Business validation rejected | info/debug depending on local practice | Operation, key IDs, reason |
| Recoverable dependency issue | warn | Dependency, retry/skip decision, correlation ID |
| Unexpected platform/system error | error | Operation, entity/form ID, safe identifiers, exception |
| Sensitive data | never log | Tokens, passwords, full payloads with personal or financial data |

Use the logger pattern already present in the target project. If no logger exists, add the smallest local logger consistent with nearby code.

---

## User Prompt Rules

Good user messages:

- Say what failed in business terms.
- Say what the user can change or retry.
- Avoid blaming platform internals.
- Avoid leaking technical details.

Bad examples:

- `NullPointerException at line 42`
- `SQL failed: select * from ...`
- `System error`

Better examples:

- `提交失败：客户资料缺少结算币别，请先维护客户资料后重试。`
- `同步失败：外部系统暂不可用，请稍后重试或联系管理员查看同步日志。`

---

## Review Checklist

- [ ] Every catch block either handles, wraps, logs, or rethrows; no silent swallow.
- [ ] Transaction helpers throw on consistency failures.
- [ ] User-facing messages are actionable and sanitized.
- [ ] Logs include safe context for troubleshooting.
- [ ] Original exception cause is preserved when wrapping.
- [ ] Tests cover validation failure, business rejection, dependency failure, and unexpected exception paths.

---

## Code Examples

### Good: Preserve Cause and Sanitize User Message

```java
try {
    syncRemoteStatus(billId);
} catch (RemoteAccessException ex) {
    logger.error("Sync remote status failed, billId={}", billId, ex);
    throw new KDBizException("同步失败：外部系统暂不可用，请稍后重试。", ex);
}
```

### Bad: Leaks Internals and Loses Context

```java
try {
    syncRemoteStatus(billId);
} catch (Exception ex) {
    ex.printStackTrace();
    throw new RuntimeException(ex.getMessage());
}
```

