Files
classroomio/packages/utils/src/constants/error-codes.ts
T
Rotimi Best f18e5600f6 fix(media): prevent attaching an asset to a target twice
Drop `position` from the `asset_usages` unique constraint so the same
asset can't be attached to one target/slot more than once, and update
the insert's onConflict target + lookup to match the narrower key.

Guard it at the service layer too: attachAssetService now rejects an
attach when the asset already has a usage for that target with a new
ASSET_ALREADY_ATTACHED (409) error, backed by an
assetUsageExistsForTarget query.
2026-06-28 23:05:57 +01:00

186 lines
7.5 KiB
TypeScript

/**
* Wire `code` values returned in API JSON error bodies (`success: false`).
* Shared by `@cio/api` and clients (e.g. dashboard snackbar mapping).
*/
export const ErrorCodes = {
// Common errors
NOT_FOUND: 'NOT_FOUND',
UNAUTHORIZED: 'UNAUTHORIZED',
// Dashboard Analytics errors
ORG_ANALYTICS_FETCH_FAILED: 'ORG_ANALYTICS_FETCH_FAILED',
NO_ORG_ID_PROVIDED: 'NO_ORG_ID_PROVIDED',
// Community errors
UPDATE_COMMUNITY_QUESTION_FAILED: 'UPDATE_COMMUNITY_QUESTION_FAILED',
ADD_COMMUNITY_QUESTION_FAILED: 'ADD_COMMUNITY_QUESTION_FAILED',
COMMUNITY_QUESTIONS_FETCH_FAILED: 'COMMUNITY_QUESTIONS_FETCH_FAILED',
COMMUNITY_QUESTION_NOT_FOUND: 'COMMUNITY_QUESTION_NOT_FOUND',
COMMENT_SUBMISSION_FAILED: 'COMMENT_SUBMISSION_FAILED',
UPVOTE_FAILED: 'UPVOTE_FAILED',
DELETE_COMMENT_FAILED: 'DELETE_COMMENT_FAILED',
DELETE_QUESTION_FAILED: 'DELETE_QUESTION_FAILED',
// Organization errors
SITENAME_EXISTS: 'SITENAME_EXISTS',
ORG_CREATE_FAILED: 'ORG_CREATE_FAILED',
ORG_NOT_FOUND: 'ORG_NOT_FOUND',
ORGANIZATION_NOT_FOUND: 'ORGANIZATION_NOT_FOUND',
ORG_TEAM_FETCH_FAILED: 'ORG_TEAM_FETCH_FAILED',
ORG_AUDIENCE_FETCH_FAILED: 'ORG_AUDIENCE_FETCH_FAILED',
COURSES_FETCH_FAILED: 'COURSES_FETCH_FAILED',
ORG_PLAN_CREATE_FAILED: 'ORG_PLAN_CREATE_FAILED',
ORG_PLAN_UPDATE_FAILED: 'ORG_PLAN_UPDATE_FAILED',
ORG_PLAN_CANCEL_FAILED: 'ORG_PLAN_CANCEL_FAILED',
ORG_PLAN_NOT_FOUND: 'ORG_PLAN_NOT_FOUND',
ORG_TEAM_INVITE_FAILED: 'ORG_TEAM_INVITE_FAILED',
ORG_TEAM_REMOVE_FAILED: 'ORG_TEAM_REMOVE_FAILED',
ORG_AUDIENCE_REMOVE_FAILED: 'ORG_AUDIENCE_REMOVE_FAILED',
ORG_TEAM_EMAIL_EXISTS: 'ORG_TEAM_EMAIL_EXISTS',
ORG_TEAM_NOT_AUTHORIZED: 'ORG_TEAM_NOT_AUTHORIZED',
ORGANIZATION_API_KEY_NOT_FOUND: 'ORGANIZATION_API_KEY_NOT_FOUND',
ORGANIZATION_API_KEY_CREATE_FAILED: 'ORGANIZATION_API_KEY_CREATE_FAILED',
ORGANIZATION_API_KEY_FETCH_FAILED: 'ORGANIZATION_API_KEY_FETCH_FAILED',
ORGANIZATION_API_KEY_REVOKE_FAILED: 'ORGANIZATION_API_KEY_REVOKE_FAILED',
ORGANIZATION_API_KEY_ROTATE_FAILED: 'ORGANIZATION_API_KEY_ROTATE_FAILED',
AUTOMATION_KEY_LIMIT_EXCEEDED: 'AUTOMATION_KEY_LIMIT_EXCEEDED',
AUTOMATION_CREDIT_LIMIT_EXCEEDED: 'AUTOMATION_CREDIT_LIMIT_EXCEEDED',
AUTOMATION_RATE_LIMIT_EXCEEDED: 'AUTOMATION_RATE_LIMIT_EXCEEDED',
TAG_GROUP_NOT_FOUND: 'TAG_GROUP_NOT_FOUND',
TAG_NOT_FOUND: 'TAG_NOT_FOUND',
TAG_FETCH_FAILED: 'TAG_FETCH_FAILED',
TAG_CREATE_FAILED: 'TAG_CREATE_FAILED',
TAG_UPDATE_FAILED: 'TAG_UPDATE_FAILED',
TAG_ASSIGNMENT_FAILED: 'TAG_ASSIGNMENT_FAILED',
WIDGET_NOT_FOUND: 'WIDGET_NOT_FOUND',
WIDGET_FETCH_FAILED: 'WIDGET_FETCH_FAILED',
WIDGET_CREATE_FAILED: 'WIDGET_CREATE_FAILED',
WIDGET_UPDATE_FAILED: 'WIDGET_UPDATE_FAILED',
WIDGET_DELETE_FAILED: 'WIDGET_DELETE_FAILED',
WIDGET_PUBLISH_FAILED: 'WIDGET_PUBLISH_FAILED',
WIDGET_ROLLBACK_FAILED: 'WIDGET_ROLLBACK_FAILED',
WIDGET_PAYLOAD_FETCH_FAILED: 'WIDGET_PAYLOAD_FETCH_FAILED',
// Asset errors
ASSET_NOT_FOUND: 'ASSET_NOT_FOUND',
ASSET_IN_USE: 'ASSET_IN_USE',
ASSET_USAGE_NOT_FOUND: 'ASSET_USAGE_NOT_FOUND',
ASSET_CREATE_FAILED: 'ASSET_CREATE_FAILED',
ASSET_FETCH_FAILED: 'ASSET_FETCH_FAILED',
ASSET_LIST_FAILED: 'ASSET_LIST_FAILED',
ASSET_UPDATE_FAILED: 'ASSET_UPDATE_FAILED',
ASSET_DELETE_FAILED: 'ASSET_DELETE_FAILED',
ASSET_ATTACH_FAILED: 'ASSET_ATTACH_FAILED',
ASSET_ALREADY_ATTACHED: 'ASSET_ALREADY_ATTACHED',
ASSET_DETACH_FAILED: 'ASSET_DETACH_FAILED',
ASSET_USAGE_FETCH_FAILED: 'ASSET_USAGE_FETCH_FAILED',
ASSET_EXPORT_FAILED: 'ASSET_EXPORT_FAILED',
ASSET_STORAGE_FETCH_FAILED: 'ASSET_STORAGE_FETCH_FAILED',
ASSET_NOT_TRANSCRIBABLE: 'ASSET_NOT_TRANSCRIBABLE',
OPENAI_KEY_MISSING: 'OPENAI_KEY_MISSING',
// Profile errors
PROFILE_UPDATE_FAILED: 'PROFILE_UPDATE_FAILED',
PROFILE_NOT_FOUND: 'PROFILE_NOT_FOUND',
// Account errors
ACCOUNT_NOT_FOUND: 'ACCOUNT_NOT_FOUND',
WORKSPACE_NOT_FOUND: 'WORKSPACE_NOT_FOUND',
WORKSPACE_LIMIT_REACHED: 'WORKSPACE_LIMIT_REACHED',
WORKSPACE_READ_ONLY: 'WORKSPACE_READ_ONLY',
WORKSPACE_IS_PRIMARY: 'WORKSPACE_IS_PRIMARY',
PLAN_UPGRADE_REQUIRED: 'PLAN_UPGRADE_REQUIRED',
NOT_PRIMARY_WORKSPACE: 'NOT_PRIMARY_WORKSPACE',
// Auth errors
FORBIDDEN: 'FORBIDDEN',
// Course errors
COURSE_NOT_FOUND: 'COURSE_NOT_FOUND',
COURSE_FETCH_FAILED: 'COURSE_FETCH_FAILED',
COURSE_IMPORT_DRAFT_NOT_FOUND: 'COURSE_IMPORT_DRAFT_NOT_FOUND',
COURSE_IMPORT_CREATE_FAILED: 'COURSE_IMPORT_CREATE_FAILED',
COURSE_IMPORT_FETCH_FAILED: 'COURSE_IMPORT_FETCH_FAILED',
COURSE_IMPORT_UPDATE_FAILED: 'COURSE_IMPORT_UPDATE_FAILED',
COURSE_IMPORT_PUBLISH_FAILED: 'COURSE_IMPORT_PUBLISH_FAILED',
SLUG_IN_USE: 'SLUG_IN_USE',
QUESTION_TYPE_NOT_ALLOWED_IN_PUBLIC_COURSE: 'QUESTION_TYPE_NOT_ALLOWED_IN_PUBLIC_COURSE',
PUBLIC_COURSE_CONVERSION_BLOCKED: 'PUBLIC_COURSE_CONVERSION_BLOCKED',
// Lesson errors
LESSON_NOT_FOUND: 'LESSON_NOT_FOUND',
LESSON_FETCH_FAILED: 'LESSON_FETCH_FAILED',
COURSE_SECTION_NOT_FOUND: 'COURSE_SECTION_NOT_FOUND',
// Exercise errors
EXERCISE_NOT_FOUND: 'EXERCISE_NOT_FOUND',
EXERCISE_FETCH_FAILED: 'EXERCISE_FETCH_FAILED',
// Submission errors
SUBMISSION_NOT_FOUND: 'SUBMISSION_NOT_FOUND',
SUBMISSION_FETCH_FAILED: 'SUBMISSION_FETCH_FAILED',
// Comment errors
COMMENT_NOT_FOUND: 'COMMENT_NOT_FOUND',
LESSON_COMMENT_UPDATE_FAILED: 'LESSON_COMMENT_UPDATE_FAILED',
NEWSFEED_COMMENT_UPDATE_FAILED: 'NEWSFEED_COMMENT_UPDATE_FAILED',
// Quiz errors
QUIZ_NOT_FOUND: 'QUIZ_NOT_FOUND',
QUIZ_FETCH_FAILED: 'QUIZ_FETCH_FAILED',
QUIZ_CREATE_FAILED: 'QUIZ_CREATE_FAILED',
QUIZ_UPDATE_FAILED: 'QUIZ_UPDATE_FAILED',
QUIZ_DELETE_FAILED: 'QUIZ_DELETE_FAILED',
// Lesson Language errors
LESSON_LANGUAGE_NOT_FOUND: 'LESSON_LANGUAGE_NOT_FOUND',
LESSON_LANGUAGE_FETCH_FAILED: 'LESSON_LANGUAGE_FETCH_FAILED',
LESSON_LANGUAGE_CREATE_FAILED: 'LESSON_LANGUAGE_CREATE_FAILED',
LESSON_LANGUAGE_UPDATE_FAILED: 'LESSON_LANGUAGE_UPDATE_FAILED',
LESSON_LANGUAGE_DELETE_FAILED: 'LESSON_LANGUAGE_DELETE_FAILED',
// SSO errors
SSO_REGISTRATION_FAILED: 'SSO_REGISTRATION_FAILED',
SSO_NOT_FOUND: 'SSO_NOT_FOUND',
SSO_NOT_ENABLED: 'SSO_NOT_ENABLED',
SOCIAL_AUTH_NOT_ENABLED: 'SOCIAL_AUTH_NOT_ENABLED',
UPGRADE_REQUIRED: 'UPGRADE_REQUIRED',
CONFLICT: 'CONFLICT',
// Token exchange errors
TOKEN_EXCHANGE_INVALID_TOKEN: 'TOKEN_EXCHANGE_INVALID_TOKEN',
TOKEN_EXCHANGE_EXPIRED: 'TOKEN_EXCHANGE_EXPIRED',
TOKEN_EXCHANGE_ORG_NOT_FOUND: 'TOKEN_EXCHANGE_ORG_NOT_FOUND',
TOKEN_EXCHANGE_NOT_ENABLED: 'TOKEN_EXCHANGE_NOT_ENABLED',
// Token auth admin errors
TOKEN_AUTH_ALREADY_EXISTS: 'TOKEN_AUTH_ALREADY_EXISTS',
// Program errors
PROGRAM_NOT_FOUND: 'PROGRAM_NOT_FOUND',
PROGRAM_FORBIDDEN: 'PROGRAM_FORBIDDEN',
PROGRAM_CREATE_FAILED: 'PROGRAM_CREATE_FAILED',
PROGRAM_UPDATE_FAILED: 'PROGRAM_UPDATE_FAILED',
PROGRAM_DELETE_FAILED: 'PROGRAM_DELETE_FAILED',
COURSE_ALREADY_IN_PROGRAM: 'COURSE_ALREADY_IN_PROGRAM',
MEMBER_ALREADY_IN_PROGRAM: 'MEMBER_ALREADY_IN_PROGRAM',
PROGRAM_MEMBER_NOT_FOUND: 'PROGRAM_MEMBER_NOT_FOUND',
PROGRAM_NEWSFEED_NOT_FOUND: 'PROGRAM_NEWSFEED_NOT_FOUND',
PROGRAM_NEWSFEED_COMMENT_NOT_FOUND: 'PROGRAM_NEWSFEED_COMMENT_NOT_FOUND',
PROGRAM_MEMBER_CHECK_FAILED: 'PROGRAM_MEMBER_CHECK_FAILED',
PROGRAM_GOAL_NOT_FOUND: 'PROGRAM_GOAL_NOT_FOUND',
PROGRAM_GOAL_CREATE_FAILED: 'PROGRAM_GOAL_CREATE_FAILED',
PROGRAM_GOAL_UPDATE_FAILED: 'PROGRAM_GOAL_UPDATE_FAILED',
PROGRAM_GOAL_DELETE_FAILED: 'PROGRAM_GOAL_DELETE_FAILED',
// AI assistant chat
NO_MESSAGES_TO_COMPACT: 'NO_MESSAGES_TO_COMPACT',
// Generic
VALIDATION_ERROR: 'VALIDATION_ERROR',
INTERNAL_ERROR: 'INTERNAL_ERROR'
} as const;
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];