Skip to content

Error Codes

API error responses and their meanings. Error codes are defined in Domain/Constants/ErrorCodes.cs and use dot-notation ({area}.{error}).

Error Response Format

Errors are returned as RFC 7807 Problem Details (application/problem+json):

{
  "status": 400,
  "detail": "Human-readable message",
  "code": "account.invalid_credentials",
  "correlationId": "abc-123-def"
}
Field Description
status HTTP status code
detail Human-readable description
code Machine-readable error code
correlationId Request tracking ID for debugging

Validation failures return ValidationProblemDetails with an additional errors dictionary. Request-body validation produces field-specific keys; ValidationException thrown from handlers uses a general key:

{
  "title": "One or more validation errors occurred.",
  "status": 400,
  "code": "common.validation_failed",
  "correlationId": "abc-123-def",
  "errors": {
    "general": ["Amount must be greater than 0"]
  }
}

HTTP Status Codes

Exceptions are mapped to statuses in GlobalExceptionHandlerMiddleware:

Status Meaning Exception
400 Bad Request ValidationException
401 Unauthorized AuthException
403 Forbidden ForbiddenException
404 Not Found MissingDataException
409 Conflict ConcurrencyException, DbIndexViolationException
429 Too Many Requests TooManyRequestsException (with Retry-After header)
500 Server Error Unhandled exceptions

Account Errors (account.*)

Code Description
account.invalid_credentials Wrong username or password
account.email_not_confirmed Email not yet confirmed
account.email_taken Email already registered
account.email_domain_blocked Email domain is on the blocklist
account.username_taken Username already registered
account.nickname_taken Nickname already in use
account.wrong_password Current password incorrect
account.same_email New email matches current email
account.invalid_confirmation_token Email confirmation token invalid
account.confirmation_expired Email confirmation token expired
account.invalid_reset_token Password reset token invalid
account.reset_token_expired Password reset token expired
account.user_not_found User doesn't exist
account.invalid_refresh_token Refresh token invalid or expired
account.refresh_token_missing Refresh token cookie not present
account.self_status_change Admin cannot change own status

Auth Errors (auth.*)

Code Description
auth.invalid_jwt Malformed or invalid access token
auth.context_unavailable HTTP context missing user identity
auth.no_group User not assigned to a group
auth.not_confirmed Registration pending admin approval
auth.declined Registration was declined
auth.deactivated Account was deactivated
auth.group_deleted User's group was deleted
auth.policy_changed Group permissions changed, token stale

Budget Errors

Code Description
budget_account.not_found Budget account doesn't exist
budget_account.duplicate Budget account name already exists
budget_account.in_use Account has transactions, cannot delete
budget_account.has_active_recurring Account used by active recurring transaction
budget_account.disabled Account is disabled
budget_account.cannot_set_disabled_as_default Disabled account cannot be default
category.not_found Category doesn't exist
category.duplicate Category name already exists
category.in_use Category has transactions, cannot delete
transaction.not_found Transaction doesn't exist
transaction.self_transfer Transfer source and target are the same
transaction.transfer_requires_target_account Transfer missing target account
transaction.non_transfer_cannot_have_target_account Only transfers may have a target account
transaction.transfer_category_must_be_null Transfers cannot have a category
transaction.non_transfer_requires_category Income/expense requires a category
transaction.account_disabled Source account is disabled
transaction.target_account_disabled Target account is disabled
recurring.not_found Recurring transaction doesn't exist

Map, Notes, and Group Errors

Code Description
marker.not_found Marker doesn't exist
note.not_found Note doesn't exist
note.forbidden Note is private to another user
note_item.not_found Note item doesn't exist
note_item.ids_invalid Item IDs don't match the note's items
group.not_found Group doesn't exist
group.duplicate Group name already exists

File Errors (file.*)

Code Description
file.not_found File doesn't exist
file.forbidden File belongs to another group/user
file.limit_reached Max images per marker reached
file.order_invalid Image order list invalid
file.empty_content Uploaded file is empty
file.too_large File exceeds size limit

Session and CAPTCHA Errors

Code Description
session.not_found Session doesn't exist
captcha.validation_failed Turnstile validation failed

Common Errors (common.*)

Code Description
common.validation_failed Request validation failed
common.duplicate_entry Unique constraint violation
common.rate_limit Too many requests, try again later
common.concurrency_conflict Resource was modified by another request
common.foreign_key_violation Referenced entity doesn't exist
common.not_null_violation Required database column was null
common.check_constraint_violation Database check constraint failed

Handling Errors (Frontend)

const handleError = (error: ApiError) => {
  switch (error.code) {
    case "common.concurrency_conflict":
      // Refresh and retry
      break;
    case "auth.policy_changed":
      // Refresh token to pick up new permissions
      break;
    default:
    // Show error message
  }
};