My App
RoomKitBackend

Error Reference

Domain-specific error types and their codes

Overview

All RoomKit errors extend the RoomKitError base class, which provides a machine-readable code and a structured context object for programmatic error handling.

import {
    RoomKitError,
    BookingConflictError,
    BookingNotFoundError,
    InvalidStateTransitionError,
    StaleVersionError,
    // ... other errors
} from '@roomkit/nestjs';

Base Class

class RoomKitError extends Error {
    public readonly code: string;
    public readonly context: Record<string, unknown>;
}

All domain errors inherit from RoomKitError. You can catch RoomKitError to handle any RoomKit-specific error, or catch a specific subclass for targeted handling.

Error Types

Error ClassCodeContext
LocationNotFoundErrorLOCATION_NOT_FOUND{ locationId }
LocationPathConflictErrorLOCATION_PATH_CONFLICT{ path }
RoomNotFoundErrorROOM_NOT_FOUND{ roomId }
CapacityExceededErrorCAPACITY_EXCEEDED{ roomId, required, available, capacityType }
BookingNotFoundErrorBOOKING_NOT_FOUND{ bookingId }
BookingConflictErrorBOOKING_CONFLICT{ roomId, startsAt, endsAt, conflictingBookingId }
PartitionConflictErrorPARTITION_CONFLICT{ roomId, partitionRoomId, conflictingBookingId }
InvalidStateTransitionErrorINVALID_STATE_TRANSITION{ bookingId, currentStatus, attemptedStatus, allowedTransitions }
StaleVersionErrorSTALE_VERSION{ bookingId, expectedVersion, actualVersion }
InvalidTimeRangeErrorINVALID_TIME_RANGE{ startsAt, endsAt, reason }
RecurrenceConflictErrorRECURRENCE_CONFLICT{ ruleId, conflictingDates }
ExamCohortOverlapErrorEXAM_COHORT_OVERLAP{ cohortId, existingSessionId, timeRange }
BulkOperationPartialErrorBULK_OPERATION_PARTIAL{ operationId, succeeded, failed, conflicts }
BlackoutConflictErrorBLACKOUT_CONFLICT{ blackoutId, locationNodeId, timeRange }
ConfigKeyInvalidErrorCONFIG_KEY_INVALID{ key, reason }
IdempotencyConflictErrorIDEMPOTENCY_CONFLICT{ idempotencyKey, existingBookingId }

Catching Specific Errors

Use instanceof checks to handle specific error types and access their typed context.

try {
    await bookingService.create(dto);
} catch (err) {
    if (err instanceof BookingConflictError) {
        const { roomId, conflictingBookingId } = err.context;
        // Handle conflict...
    }
}

Examples

Handling State Transition Errors

try {
    await bookingService.confirm(bookingId, 'admin-1');
} catch (err) {
    if (err instanceof InvalidStateTransitionError) {
        const { currentStatus, attemptedStatus, allowedTransitions } = err.context;
        console.log(
            `Cannot transition from ${currentStatus} to ${attemptedStatus}. ` +
            `Allowed transitions: ${allowedTransitions}`,
        );
    }
}

Handling Optimistic Concurrency

try {
    await bookingService.modify(bookingId, changes, expectedVersion);
} catch (err) {
    if (err instanceof StaleVersionError) {
        const { expectedVersion, actualVersion } = err.context;
        console.log(
            `Version conflict: expected ${expectedVersion}, ` +
            `but booking is at version ${actualVersion}. Refetch and retry.`,
        );
    }
}

Handling Idempotency Conflicts

try {
    await bookingService.create({
        ...dto,
        idempotencyKey: 'meeting-2026-03-02',
    });
} catch (err) {
    if (err instanceof IdempotencyConflictError) {
        const { existingBookingId } = err.context;
        // Return the existing booking instead of creating a duplicate
        return bookingService.getById(existingBookingId);
    }
}

Catching All RoomKit Errors

try {
    await bookingService.create(dto);
} catch (err) {
    if (err instanceof RoomKitError) {
        console.error(`RoomKit error [${err.code}]:`, err.message);
        console.error('Context:', err.context);
    } else {
        throw err; // Re-throw non-RoomKit errors
    }
}

On this page