API Error Codes Reference
All GoodGo Platform API errors follow a structured JSON format. This document lists every errorCode value, its HTTP status, description, and usage examples.
Error Response Format
Every error response from the API has this shape:
| Field |
Type |
Description |
statusCode |
number |
HTTP status code (e.g. 400, 401, 404). |
errorCode |
string |
Machine-readable error identifier (see tables below). |
message |
string |
Human-readable explanation (Vietnamese for business rules, English for system errors). |
details |
object |
Optional structured metadata (e.g. validation field names, current/target status). |
correlationId |
string |
Echoed from the X-Correlation-Id request header when present. |
timestamp |
string |
ISO 8601 timestamp of the error occurrence. |
General Error Codes
These codes apply across all modules. They are also used as fallback codes when a plain HttpException (without a domain error code) is thrown.
| Error Code |
HTTP Status |
Description |
When It Occurs |
INTERNAL_ERROR |
500 |
Unexpected server error. |
Unhandled exceptions, infrastructure failures. |
VALIDATION_FAILED |
400 |
Request data failed validation. |
Invalid input fields, business rule violations (e.g. invalid phone format, bad status transitions). |
NOT_FOUND |
404 |
Requested resource does not exist. |
Entity lookup by ID returns no result. |
CONFLICT |
409 |
Resource state conflict. |
Duplicate creation, conflicting state transition. |
UNAUTHORIZED |
401 |
Authentication required or failed. |
Missing/invalid/expired auth token, bad credentials. |
FORBIDDEN |
403 |
Insufficient permissions. |
Role-based access denial, CSRF token failure, resource ownership mismatch. |
BAD_REQUEST |
400 |
Malformed request. |
Invalid file upload, unsupported content type, bad query parameters. |
TOO_MANY_REQUESTS |
429 |
Rate limit exceeded. |
Too many API requests in a short period. |
Auth Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
AUTH_INVALID_CREDENTIALS |
401 |
Login credentials are incorrect. |
Phone number or password mismatch during local login. |
AUTH_TOKEN_EXPIRED |
401 |
JWT token has expired. |
Access token or refresh token past expiration. |
AUTH_TOKEN_INVALID |
401 |
JWT token is malformed or tampered with. |
Token signature verification failure. |
AUTH_INSUFFICIENT_PERMISSIONS |
403 |
Authenticated user lacks required role/permission. |
Non-admin accessing admin endpoints, role mismatch. |
Auth Module Usage Examples
User Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
USER_NOT_FOUND |
404 |
User does not exist. |
Profile lookup, admin user management. |
USER_ALREADY_EXISTS |
409 |
User with given identifier already exists. |
Duplicate registration (phone or email). |
USER_INVALID_PHONE |
400 |
Phone number format is invalid. |
Registration or profile update with bad phone format. |
User Module Usage Examples
Listing Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
LISTING_NOT_FOUND |
404 |
Listing does not exist. |
Lookup by ID for viewing, moderation, or status change. |
LISTING_INVALID_STATUS_TRANSITION |
400 |
Status transition is not allowed. |
Attempting an invalid workflow step (e.g. EXPIRED → ACTIVE). |
LISTING_ALREADY_ACTIVE |
409 |
Listing is already in active state. |
Re-activating a listing that is already published. |
LISTING_EXPIRED |
400 |
Listing has expired. |
Attempting operations on an expired listing. |
Listing Module Usage Examples
Property Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
PROPERTY_NOT_FOUND |
404 |
Property does not exist. |
Property lookup for media upload or listing creation. |
Property Module Usage Examples
Media Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
MEDIA_UPLOAD_FAILED |
500 |
File upload to storage provider failed. |
S3/cloud storage write failure. |
MEDIA_LIMIT_EXCEEDED |
400 |
Maximum number of media files reached. |
Exceeding per-property media limit. |
Payment Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
PAYMENT_FAILED |
500 |
Payment processing failed. |
Gateway error, provider timeout, payment link creation failure. |
PAYMENT_ALREADY_PROCESSED |
409 |
Payment has already been completed, failed, or refunded. |
Duplicate callback, retry on non-pending payment, refunding a non-completed payment. |
PAYMENT_INVALID_AMOUNT |
400 |
Payment amount is invalid. |
Zero/negative amount, amount below minimum threshold. |
Payment Module Usage Examples
Subscription Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
SUBSCRIPTION_NOT_FOUND |
404 |
Subscription does not exist. |
Lookup for cancellation, upgrade, or usage metering. |
SUBSCRIPTION_ALREADY_ACTIVE |
409 |
User already has an active subscription. |
Attempting to create a second active subscription. |
SUBSCRIPTION_ALREADY_CANCELLED |
409 |
Subscription has already been cancelled. |
Re-cancelling a subscription. |
SUBSCRIPTION_INACTIVE |
409 |
Subscription is not in an active state. |
Upgrading, expiring, or marking past-due on a non-active subscription. |
QUOTA_EXCEEDED |
403 |
Usage quota for the current plan has been exceeded. |
Exceeding listing, lead, or search quota limits. |
Subscription Module Usage Examples
Course Error Codes
| Error Code |
HTTP Status |
Description |
When It Occurs |
COURSE_NOT_FOUND |
404 |
Course does not exist. |
Course lookup by ID. |
COURSE_ALREADY_PUBLISHED |
409 |
Course is already in published state. |
Re-publishing an active course. |
COURSE_ENROLLMENT_CLOSED |
400 |
Course enrollment period has ended. |
Attempting to enroll after the cutoff date. |
Error Code Quick-Reference (Sorted Alphabetically)
| Error Code |
HTTP Status |
Module |
AUTH_INSUFFICIENT_PERMISSIONS |
403 |
Auth |
AUTH_INVALID_CREDENTIALS |
401 |
Auth |
AUTH_TOKEN_EXPIRED |
401 |
Auth |
AUTH_TOKEN_INVALID |
401 |
Auth |
BAD_REQUEST |
400 |
General |
CONFLICT |
409 |
General |
COURSE_ALREADY_PUBLISHED |
409 |
Course |
COURSE_ENROLLMENT_CLOSED |
400 |
Course |
COURSE_NOT_FOUND |
404 |
Course |
FORBIDDEN |
403 |
General |
INTERNAL_ERROR |
500 |
General |
LISTING_ALREADY_ACTIVE |
409 |
Listing |
LISTING_EXPIRED |
400 |
Listing |
LISTING_INVALID_STATUS_TRANSITION |
400 |
Listing |
LISTING_NOT_FOUND |
404 |
Listing |
MEDIA_LIMIT_EXCEEDED |
400 |
Media |
MEDIA_UPLOAD_FAILED |
500 |
Media |
NOT_FOUND |
404 |
General |
PAYMENT_ALREADY_PROCESSED |
409 |
Payment |
PAYMENT_FAILED |
500 |
Payment |
PAYMENT_INVALID_AMOUNT |
400 |
Payment |
PROPERTY_NOT_FOUND |
404 |
Property |
QUOTA_EXCEEDED |
403 |
Subscription |
SUBSCRIPTION_ALREADY_ACTIVE |
409 |
Subscription |
SUBSCRIPTION_ALREADY_CANCELLED |
409 |
Subscription |
SUBSCRIPTION_INACTIVE |
409 |
Subscription |
SUBSCRIPTION_NOT_FOUND |
404 |
Subscription |
TOO_MANY_REQUESTS |
429 |
General |
UNAUTHORIZED |
401 |
General |
USER_ALREADY_EXISTS |
409 |
User |
USER_INVALID_PHONE |
400 |
User |
USER_NOT_FOUND |
404 |
User |
Frontend Integration Guide
TypeScript Error Type
Handling Errors by Code
Error Code Constants (Optional)
For type safety, maintain error codes as a union type on the frontend:
Source Files
- Error code enum:
apps/api/src/modules/shared/domain/error-codes.ts
- Domain exceptions:
apps/api/src/modules/shared/domain/domain-exception.ts
- Global exception filter:
apps/api/src/modules/shared/infrastructure/filters/global-exception.filter.ts