Skip to main content

Error Codes

Comprehensive reference for all error codes returned by the Exam Portal API.

HTTP Status Codes

StatusCategoryMeaning
200SuccessRequest succeeded
201SuccessResource created
204SuccessNo content
400Client ErrorBad request/validation error
401Client ErrorUnauthorized (invalid/missing token)
403Client ErrorForbidden (insufficient permissions)
404Client ErrorResource not found
409Client ErrorConflict (resource already exists)
429Client ErrorRate limited
500Server ErrorInternal server error
503Server ErrorService unavailable

Error Response Format

{
"error": "ERROR_CODE",
"message": "Human readable message",
"status": 400,
"details": {
"field": "additional_context"
}
}

Authentication Errors (401)

MISSING_AUTH_TOKEN

{
"error": "Missing authentication token",
"code": "MISSING_AUTH_TOKEN",
"status": 401
}

Cause: Request missing Authorization: Bearer header

Solution: Add Firebase ID token to request header

INVALID_TOKEN

{
"error": "Invalid or expired token",
"code": "INVALID_TOKEN",
"status": 401
}

Cause: Token is malformed, expired, or from wrong Firebase project

Solution: Get fresh token from Firebase Authentication

TOKEN_VERIFICATION_FAILED

{
"error": "Token verification failed",
"code": "TOKEN_VERIFICATION_FAILED",
"status": 401
}

Cause: Token signature validation failed

Solution: Ensure token is from correct Firebase project

TOKEN_EXPIRED

{
"error": "ID token has expired",
"code": "TOKEN_EXPIRED",
"status": 401
}

Solution: Refresh token with getIdToken(true) or firebase.auth().currentUser.getIdToken(true)

Authorization Errors (403)

FORBIDDEN

{
"error": "Permission denied",
"code": "FORBIDDEN",
"status": 403
}

Cause: User lacks required role for operation

Solution: Verify user role (Super Admin, Client Admin, Student)

BOLA_VIOLATION

{
"error": "Attempting to access other organization's data",
"code": "BOLA_VIOLATION",
"status": 403
}

Cause: Attempting to access resource from different tenant

Solution: Verify client_id matches user's organization

IDOR_VIOLATION

{
"error": "Direct object reference without authorization",
"code": "IDOR_VIOLATION",
"status": 403
}

Cause: Direct object reference without ownership validation

Solution: System prevented unauthorized access — use your own resources only

TENANT_MISMATCH

{
"error": "Permission denied: Tenant mismatch",
"code": "TENANT_MISMATCH",
"status": 403
}

Solution: Access only your organization's resources

INSUFFICIENT_PRIVILEGES

{
"error": "Insufficient privileges for this operation",
"code": "INSUFFICIENT_PRIVILEGES",
"status": 403
}

Solution: Use appropriate user role (e.g., Super Admin for client management)

ATTEMPT_TOKEN_INVALID

{
"error": "Permission denied: Invalid attempt token",
"code": "ATTEMPT_TOKEN_INVALID",
"status": 403
}

Cause: Guest attempt missing or incorrect attempt_token

Solution: Include correct attempt_token in query or header for guest operations

ATTEMPT_NOT_OWNER

{
"error": "You do not own this attempt",
"code": "ATTEMPT_NOT_OWNER",
"status": 403
}

Cause: Student accessing another student's attempt

Solution: Only access your own attempts

SECTION_LOCKED

{
"error": "Section navigation locked",
"code": "SECTION_LOCKED",
"status": 403
}

Cause: Attempting to return to a completed section with navigation locked

Solution: Cannot edit answers in locked sections

Validation Errors (400)

VALIDATION_ERROR

{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"status": 400,
"details": [
{
"field": "test_name",
"message": "Test name is required"
},
{
"field": "timer",
"message": "Timer must be positive integer"
}
]
}

Cause: Invalid or missing required fields

Solution: Check field requirements and data types

INVALID_EMAIL

{
"error": "Email format is invalid",
"code": "INVALID_EMAIL",
"status": 400
}

Solution: Provide valid email address

INVALID_UUID

{
"error": "ID format is not valid UUID",
"code": "INVALID_UUID",
"status": 400
}

Solution: Use valid UUID format

MISSING_FIELD

{
"error": "Required field is missing",
"code": "MISSING_FIELD",
"status": 400
}

Solution: Include all required fields in request

INVALID_TEST_CONFIGURATION

{
"error": "Invalid test configuration",
"code": "INVALID_TEST_CONFIGURATION",
"status": 400,
"details": {
"reason": "Timer cannot be less than 5 minutes"
}
}

Solution: Verify timer, limits, and configuration values

INVALID_QUESTION_TYPE

{
"error": "Invalid question type",
"code": "INVALID_QUESTION_TYPE",
"status": 400
}

Cause: Question type not in (mcq, true_false, multi_select, fill_blank, subjective, coding)

Solution: Use supported question type

CSV_IMPORT_VALIDATION_ERROR

{
"error": "CSV import validation failed",
"code": "CSV_IMPORT_VALIDATION_ERROR",
"status": 400,
"details": {
"line": 5,
"error": "Missing required column: correct_answer",
"row_data": "What is 2+2?,mcq,3,4,5,6,,1,easy"
}
}

Solution: Verify CSV has headers: question_text, question_type, option_a, option_b, correct_answer, marks

CAMERA_PERMISSION_DENIED

{
"error": "Camera permission denied",
"code": "CAMERA_PERMISSION_DENIED",
"status": 400,
"details": {
"event_type": "CAMERA_PERMISSION_DENIED",
"message": "Browser denied camera access"
}
}

Solution: Grant camera permission in browser settings

CAMERA_NOT_AVAILABLE

{
"error": "Camera device not available",
"code": "CAMERA_NOT_AVAILABLE",
"status": 400
}

Solution: Check camera device availability

PROCTORING_NOT_ENABLED

{
"error": "Proctoring is not enabled for this test",
"code": "PROCTORING_NOT_ENABLED",
"status": 400
}

Solution: Test must have proctoring feature enabled

Resource Errors (404)

NOT_FOUND

{
"error": "Resource not found",
"code": "NOT_FOUND",
"status": 404,
"details": {
"resource_type": "Test",
"resource_id": "invalid-uuid"
}
}

Solution: Verify resource ID is correct

CLIENT_NOT_FOUND

{
"error": "Client organization not found",
"code": "CLIENT_NOT_FOUND",
"status": 404
}

Solution: Verify client ID

TEST_NOT_FOUND

{
"error": "Test not found",
"code": "TEST_NOT_FOUND",
"status": 404
}

Solution: Verify test ID or share code

QUESTION_NOT_FOUND

{
"error": "Question not found",
"code": "QUESTION_NOT_FOUND",
"status": 404
}

Solution: Verify question ID

ATTEMPT_NOT_FOUND

{
"error": "Attempt not found",
"code": "ATTEMPT_NOT_FOUND",
"status": 404
}

Solution: Verify attempt ID

INVALID_SHARE_CODE

{
"error": "Invalid share code",
"code": "INVALID_SHARE_CODE",
"status": 404
}

Solution: Verify share code and try again

RESOURCE_DELETED

{
"error": "Resource has been deleted",
"code": "RESOURCE_DELETED",
"status": 410
}

Solution: Cannot access deleted resources

Subscription & Billing Errors (400 / 409)

SUBSCRIPTION_EXPIRED

{
"error": "Client subscription has expired",
"code": "SUBSCRIPTION_EXPIRED",
"status": 400
}

Solution: Contact Super Admin to renew subscription

QUOTA_EXCEEDED

{
"error": "Quota exceeded: Monthly exam limit reached",
"code": "QUOTA_EXCEEDED",
"status": 400,
"details": {
"limit": 3,
"current_usage": 3,
"resource": "exams_per_month"
}
}

Solution: Upgrade subscription or use Pay Per Test packages

INSUFFICIENT_PACKAGE_CAPACITY

{
"error": "Insufficient package capacity",
"code": "INSUFFICIENT_PACKAGE_CAPACITY",
"status": 400,
"details": {
"limit": 50,
"requested": 75,
"resource": "questions"
}
}

Solution: Select higher capacity package or upgrade

PACKAGE_ALREADY_USED

{
"error": "Package has already been used",
"code": "PACKAGE_ALREADY_USED",
"status": 409
}

Solution: Purchase new package for new test

Exam Engine Errors (400 / 403 / 409)

TEST_NOT_PUBLISHED

{
"error": "Test is not published",
"code": "TEST_NOT_PUBLISHED",
"status": 400
}

Solution: Client Admin must publish test first

TEST_NOT_ACTIVE

{
"error": "Test is not currently active",
"code": "TEST_NOT_ACTIVE",
"status": 400
}

Solution: Wait for test to be activated by admin

OUTSIDE_SCHEDULED_WINDOW

{
"error": "Test is outside scheduled time window",
"code": "OUTSIDE_SCHEDULED_WINDOW",
"status": 400,
"details": {
"scheduled_start": "2026-06-25T10:00:00Z",
"scheduled_end": "2026-06-25T12:00:00Z",
"current_time": "2026-06-26T10:00:00Z"
}
}

Solution: Wait for scheduled start or contact admin

GUEST_ACCESS_NOT_ALLOWED

{
"error": "Guest access is not allowed for this test",
"code": "GUEST_ACCESS_NOT_ALLOWED",
"status": 403
}

Solution: Use registered student account or ask admin to enable guest access

ATTEMPT_LIMIT_EXCEEDED

{
"error": "Attempt limit exceeded",
"code": "ATTEMPT_LIMIT_EXCEEDED",
"status": 400,
"details": {
"allowed_attempts": 1,
"current_attempts": 1
}
}

Solution: Cannot take more attempts unless admin changes limit

CANDIDATE_CAPACITY_REACHED

{
"error": "Candidate capacity reached for this test",
"code": "CANDIDATE_CAPACITY_REACHED",
"status": 403
}

Solution: Purchase package with higher capacity

TEST_READ_ONLY

{
"error": "Test is read-only",
"code": "TEST_READ_ONLY",
"status": 400
}

Solution: Cannot modify test configuration when read-only

DUPLICATE_ANSWER_SUBMISSION

{
"error": "Attempt has already been submitted",
"code": "DUPLICATE_ANSWER_SUBMISSION",
"status": 409
}

Solution: Cannot resubmit. View results or start new attempt

ALREADY_EXISTS

{
"error": "Resource already exists",
"code": "ALREADY_EXISTS",
"status": 409
}

Solution: Use different identifier or update existing

STATE_CONFLICT

{
"error": "Resource state conflict",
"code": "STATE_CONFLICT",
"status": 409,
"details": {
"expected_state": "draft",
"actual_state": "published"
}
}

Solution: Change resource state first or different operation

Rate Limiting Errors (429)

RATE_LIMITED

{
"error": "Too many requests, please try again later",
"code": "RATE_LIMITED",
"status": 429,
"details": {
"retry_after": 60,
"limit": 100,
"window": "1 minute"
}
}

Cause: Exceeded API rate limit

Solution: Wait before retrying (see Retry-After header or retry_after value)

QUOTA_EXCEEDED

{
"error": "Monthly quota exceeded",
"code": "QUOTA_EXCEEDED",
"status": 429
}

Solution: Upgrade plan or wait for renewal

Server Errors (500)

SERVER_ERROR

{
"error": "Internal server error",
"code": "SERVER_ERROR",
"status": 500
}

Solution: Contact support if persists

DATABASE_ERROR

{
"error": "Database operation failed",
"code": "DATABASE_ERROR",
"status": 500
}

Cause: Database query or connection failed

Solution: Retry request; if persists, contact support

SERVICE_UNAVAILABLE

{
"error": "Service temporarily unavailable",
"code": "SERVICE_UNAVAILABLE",
"status": 503,
"details": {
"reason": "maintenance_mode",
"message": "Platform is under maintenance"
}
}

Solution: Wait for maintenance to complete

Error Handling Best Practices

Retry with Exponential Backoff

async function apiCallWithRetry(endpoint, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(endpoint, options);

if (response.status === 429) {
const retryAfter =
response.headers.get("Retry-After") || Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}

if (response.status >= 500) {
if (attempt < maxRetries - 1) {
await new Promise((resolve) =>
setTimeout(resolve, Math.pow(2, attempt) * 1000),
);
continue;
}
}

return response;
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise((resolve) =>
setTimeout(resolve, Math.pow(2, attempt) * 1000),
);
}
}
}

Error Classification

function classifyError(response) {
const { status, code } = response;

if (status === 401) return "AUTHENTICATION_ERROR";
if (status === 403) return "AUTHORIZATION_ERROR";
if (status === 400) return "VALIDATION_ERROR";
if (status === 429) return "RATE_LIMIT_ERROR";
if (status >= 500) return "SERVER_ERROR";

return "UNKNOWN_ERROR";
}

Debugging Tips

Check Error Details

# Enable verbose logging
curl -v -X GET https://api.nssoftwaresolutions.in/api/tests \
-H "Authorization: Bearer $TOKEN"

Monitor Headers

Response headers often contain additional information:

X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705320000
X-Request-Id: req-12345

Review Logs

Access application logs in GCP Cloud Logging with request IDs for detailed error traces.

Next Steps