Error Codes¶
ICOSYS uses a global IC-* error code system. Every error response includes a structured JSON body with a machine-readable code, a human-readable message, and a correlation ID for log tracing.
Error Response Format¶
All backend errors return this consistent JSON structure:
{
"status": "ERROR",
"error_code": "IC-BPM-4001",
"message": "Business partner not found",
"ref_id": "a3f8b2c9",
"http_status": 404,
"timestamp": "2026-02-15T10:30:00Z",
"path": "/api/business-partner/999"
}
| Field | Type | Description |
|---|---|---|
status |
string |
Always "ERROR" |
error_code |
string |
IC-* code (see registry below) |
message |
string |
Localized message (EN/TR based on Accept-Language) |
ref_id |
string |
8-character correlation ID for log lookup |
http_status |
int |
HTTP status code |
timestamp |
string |
ISO-8601 timestamp |
path |
string |
Request URI |
Log Correlation
Use ref_id to find the full stack trace in exception logs:
Error Code Format¶
| Part | Values | Description |
|---|---|---|
IC |
Fixed prefix | ICOSYS platform |
MODULE |
SYS, BPM, DMS |
Source module |
CATEGORY |
1xxx–6xxx |
Error category (see below) |
SEQUENCE |
001–999 |
Unique within category |
Categories¶
| Range | Category | Description |
|---|---|---|
| 1xxx | Authentication | Login, session, token errors |
| 2xxx | Validation | Field required, business rule violations |
| 3xxx | API / Network | Service unavailable, timeouts, not found |
| 4xxx | Data / CRUD | Entity not found, version conflict, references |
| 5xxx | File / Storage | Upload validation, storage failures (DMS only) |
| 6xxx | System | Unexpected errors, parse errors |
IC-SYS — System Errors¶
Platform-wide errors that apply to all services.
Authentication (1xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-SYS-1001 |
401 | error | Session expired — token is no longer valid |
IC-SYS-1002 |
403 | error | Access denied — insufficient permissions |
IC-SYS-1003 |
401 | error | Invalid token — malformed or tampered JWT |
Validation (2xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-SYS-2001 |
400 | warn | Required field is missing or blank |
IC-SYS-2002 |
400 | warn | Generic validation error |
API / Network (3xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-SYS-3001 |
503 | error | Service unavailable |
IC-SYS-3002 |
504 | error | Request timeout |
IC-SYS-3003 |
404 | warn | Resource not found |
IC-SYS-3004 |
405 | warn | HTTP method not allowed |
IC-SYS-3005 |
415 | warn | Media type not supported |
Data / CRUD (4xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-SYS-4001 |
404 | error | Entity not found by ID |
IC-SYS-4002 |
409 | error | Version conflict — record modified by another user |
IC-SYS-4003 |
409 | error | Cannot delete — record is referenced by other data |
System (6xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-SYS-6001 |
500 | error | Unexpected internal error |
IC-SYS-6002 |
400 | warn | JSON parse error — malformed request body |
IC-BPM — Business Partner Management¶
Validation (2xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-BPM-2001 |
400 | warn | Required field is missing |
IC-BPM-2002 |
409 | warn | Tax number already exists for this tenant |
IC-BPM-2003 |
409 | warn | Branch name already exists for this partner |
IC-BPM-2004 |
400 | warn | Contract dates are invalid (end before start) |
IC-BPM-2005 |
400 | warn | Partner must be marked as customer or vendor |
IC-BPM-2006 |
409 | warn | Default branch already exists for this partner |
IC-BPM-2007 |
409 | warn | Primary contact already exists for this partner |
IC-BPM-2008 |
409 | warn | Accrual period already exists (duplicate period) |
IC-BPM-2009 |
400 | warn | Accrual cannot be updated in current status |
IC-BPM-2010 |
400 | warn | Accrual cannot be deleted in current status |
IC-BPM-2011 |
400 | warn | Accrual cannot be approved in current status |
IC-BPM-2012 |
400 | warn | Accrual cannot be invoiced in current status |
IC-BPM-2013 |
400 | warn | Accrual cannot be cancelled in current status |
IC-BPM-2014 |
400 | error | Invalid tenant — crProcessId not found |
Data (4xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-BPM-4001 |
404 | error | Entity not found |
IC-DMS — Document Management¶
Validation (2xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-DMS-2001 |
409 | warn | Category name already exists in this tenant |
IC-DMS-2002 |
400 | warn | Category circular reference detected |
IC-DMS-2003 |
400 | warn | Category has child categories — delete children first |
IC-DMS-2004 |
410 | warn | Share link has expired |
IC-DMS-2005 |
401 | warn | Share link requires a password |
IC-DMS-2006 |
401 | warn | Share link password is incorrect |
IC-DMS-2007 |
410 | warn | Signed download URL has expired |
IC-DMS-2008 |
403 | error | Signed download URL is invalid (tampered) |
IC-DMS-2009 |
409 | warn | Account config already exists for this tenant |
IC-DMS-2010 |
410 | warn | Share link is inactive |
IC-DMS-2011 |
429 | warn | Share link download limit reached |
Data (4xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-DMS-4001 |
404 | error | File not found |
IC-DMS-4002 |
404 | error | Category not found |
IC-DMS-4003 |
404 | error | Share link not found |
File / Storage (5xxx)¶
| Code | HTTP | Severity | Description |
|---|---|---|---|
IC-DMS-5001 |
400 | warn | Uploaded file is empty |
IC-DMS-5002 |
413 | warn | File exceeds maximum allowed size |
IC-DMS-5003 |
415 | warn | File extension is not in the allowed list |
IC-DMS-5004 |
415 | error | Dangerous file extension detected (e.g., .exe, .bat) |
IC-DMS-5005 |
415 | error | File magic number does not match declared extension |
IC-DMS-5006 |
403 | error | Path traversal attempt detected in filename |
IC-DMS-5007 |
500 | error | File storage operation failed |
IC-DMS-5008 |
413 | warn | Storage quota exceeded for this tenant |
IC-DMS-5009 |
400 | warn | Invalid file name (illegal characters) |
IC-DMS-5010 |
500 | error | File read operation failed |
IC-DMS-5011 |
500 | error | File store operation failed |
IC-DMS-5012 |
500 | error | File checksum verification failed |
IC-DMS-5013 |
404 | error | Physical file not found on storage |
IC-DMS-5014 |
500 | error | File retrieval from storage failed |
IC-DMS-5015 |
500 | error | Signed URL computation failed |
HTTP Status Code Mapping¶
When the backend returns a plain HTTP error without an IC-* code, the frontend maps the status to a default code:
| HTTP Status | Default IC Code | Description |
|---|---|---|
| 400 | IC-SYS-2002 |
Bad request / validation error |
| 401 | IC-SYS-1001 |
Unauthorized / session expired |
| 403 | IC-SYS-1002 |
Forbidden / access denied |
| 404 | IC-SYS-3003 |
Resource not found |
| 409 | IC-SYS-4002 |
Conflict / version mismatch |
| 413 | IC-DMS-5002 |
Payload too large |
| 415 | IC-SYS-3005 |
Unsupported media type |
| 429 | — | Rate limited (Retry-After header) |
| 500 | IC-SYS-6001 |
Internal server error |
| 502 / 503 | IC-SYS-3001 |
Service unavailable |
| 504 | IC-SYS-3002 |
Gateway timeout |
Backend Exception Handling¶
GlobalExceptionHandler¶
All services use a shared GlobalExceptionHandler (@ControllerAdvice) that:
- Catches every exception (including Spring framework exceptions)
- Generates an 8-character
refIdfor correlation - Logs the full exception to the database (
s_exception_logtable) - Returns the structured error JSON response
- Resolves message language from
Accept-Languageheader
ServiceException("IC-BPM-2002", "Tax number exists")
→ GlobalExceptionHandler.handleServiceException()
→ Generate refId: "a3f8b2c9"
→ Log to DB: refId, stackTrace, requestInfo, user
→ Return: { error_code, message, ref_id, http_status, ... }
ServiceException¶
All business logic errors throw ServiceException with an IC-* code:
Exception Log Entry¶
Each logged exception contains:
| Field | Description |
|---|---|
refId |
8-character correlation ID (returned to client) |
logUuid |
Full UUID for internal reference |
errorCode |
IC-* code |
message |
Exception message |
stackTrace |
Full Java stack trace |
requestUri |
Request URL |
requestParams |
Query parameters |
httpMethod |
GET, POST, PUT, DELETE |
userCode |
Authenticated user (from JWT) |
ipAddress |
Client IP |
userAgent |
Browser/client identifier |
severity |
ERROR, WARN, INFO |
createdAt |
Timestamp |
Frontend Error Handling¶
Error Flow¶
API call fails
│
▼
Axios interceptor
├─ 401 → Clear session → Redirect /login
└─ Other → Parse response body
│
▼
ApiError class
{ errorCode, refId, httpStatus, userMessage }
│
▼
handleApiError()
├─ Lookup IC-* code in frontend registry
├─ Get localized message (TR/EN)
└─ Show toast notification
ApiError Class¶
class ApiError {
errorCode: string // "IC-BPM-4001"
refId: string // "a3f8b2c9"
httpStatus: number // 404
userMessage: string // Localized message from backend
}
Error Code Registry (Frontend)¶
The frontend maintains a parallel registry of all IC-* codes with bilingual messages:
{
"IC-SYS-4002": {
severity: "error",
category: "data",
en: "This record was modified by another user. Please refresh and try again.",
tr: "Bu kayıt başka bir kullanıcı tarafından değiştirildi. Lütfen yenileyip tekrar deneyin."
},
"IC-DMS-5002": {
severity: "warn",
category: "file",
en: "File exceeds maximum allowed size.",
tr: "Dosya izin verilen maksimum boyutu aşıyor."
}
}
Toast Display¶
try {
await service.create(data)
} catch (error) {
handleApiError(error)
// Shows toast: "[IC-BPM-2002] Bu vergi numarası zaten kullanılıyor. (ref: a3f8b2c9)"
}
| Severity | Toast Type | Duration |
|---|---|---|
error |
Red error toast | 8 seconds |
warn |
Yellow warning toast | 5 seconds |
info |
Blue info toast | 3 seconds |
Error Display Message¶
For inline error banners (e.g., form validation):
const message = getErrorDisplayMessage(error)
// Returns: "IC-BPM-4001 - Business partner not found (ref: a3f8b2c9)"
Common Error Scenarios¶
Optimistic Lock Failure¶
User A loads record (version: 3)
User B loads record (version: 3)
User A saves → success (version: 4)
User B saves → 409 Conflict, IC-SYS-4002
{
"error_code": "IC-SYS-4002",
"message": "This record was modified by another user. Please refresh and try again.",
"ref_id": "d4e5f6a7"
}
Frontend shows an error toast with a "Reload" button.
Referential Integrity Violation¶
{
"error_code": "IC-SYS-4003",
"message": "Cannot delete: This record is referenced by other data.",
"ref_id": "e5f6a7b8"
}
File Upload Rejection¶
{
"error_code": "IC-DMS-5005",
"message": "File magic number does not match the declared extension.",
"ref_id": "f6a7b8c9"
}
This catches files where the extension has been renamed (e.g., .exe renamed
to .pdf).
Rate Limit Exceeded¶
{
"status": 429,
"message": "Rate limit exceeded. Maximum 200 requests per minute allowed.",
"retryAfter": 60
}
Adding New Error Codes¶
Backend¶
-
Add the constant to
ErrorCodes.java(or module-specificServiceErrorMsgCodes): -
Add messages to
messages.propertiesandmessages_tr.properties: -
Throw in service code:
Frontend¶
Add the code to the frontend registry:
"IC-HRM-2001": {
severity: "warn",
category: "validation",
en: "Employee email already exists.",
tr: "Çalışan e-posta adresi zaten mevcut."
}
What's Next?¶
- REST API — Full endpoint reference for all services
- Authentication — JWT flow, API keys, security filters