Skip to content
页面信息
📝 描述Hydro 插件开发中可用的所有错误类型,包括基础错误类和自定义业务错误

错误类 (Error Classes)

Hydro 插件开发中可用的所有错误类型,包括基础错误类和 Hydro 自定义业务错误。

Source: packages/hydrooj/src/error.ts, @hydrooj/framework/error

导入

ts
import {
    HydroError, UserFacingError, BadRequestError, ForbiddenError, NotFoundError,
    CreateError,
    // ... 自定义错误类
} from 'hydrooj';

CreateError 工厂函数

CreateError 用于创建自定义错误类。所有 Hydro 内置错误均通过此函数生成。

签名

ts
function CreateError(
    name: string,
    Base: typeof UserFacingError,
    message: string | ((this: HydroError) => string),
    httpStatus?: number
): typeof UserFacingError;

参数

参数类型说明
namestring错误类名称,同时作为错误 name 属性
Basetypeof UserFacingError父错误类,决定 HTTP 状态码默认值
messagestring | (this: HydroError) => string错误消息模板,支持 {0} {1} {2} 占位符;或返回消息的函数
httpStatusnumber可选,覆盖 HTTP 状态码

用法示例

ts
import { CreateError, ForbiddenError } from 'hydrooj';

// 简单消息 + 占位符
export const MyError = CreateError('MyError', ForbiddenError, 'Something went wrong: {0}');

// 动态消息(基于 this.params 计算)
export const DynamicError = CreateError('DynamicError', ForbiddenError, function (this: HydroError) {
    return `Value is ${this.params[0]}`;
});

// 抛出
throw new MyError('detail info');

消息模板中的 {0}{1}{2} 会被替换为构造函数传入的参数(this.params)。


基础错误类

@hydrooj/framework/error 导出,构成错误继承体系。

类名HTTP 状态码说明
HydroError所有 Hydro 错误的基类。持有 nameparamsmessage 属性
UserFacingError500面向用户的错误基类,继承 HydroError。带 HTTP 状态码
BadRequestError400请求参数或业务逻辑无效,继承 UserFacingError
ForbiddenError403权限不足或操作被拒绝,继承 UserFacingError
NotFoundError404资源不存在,继承 UserFacingError

继承关系:

HydroError
└── UserFacingError (500)
    ├── BadRequestError (400)
    ├── ForbiddenError (403)
    └── NotFoundError (404)

Hydro 自定义错误

以下错误均定义于 packages/hydrooj/src/error.ts,通过 CreateError 创建。

Internal / Server Error (500)

继承 UserFacingError,表示服务端异常。

错误类默认消息
RemoteOnlineJudgeErrorRemoteOnlineJudgeError
SendMailErrorFailed to send mail to {0}. (1)

Permission / Auth Errors (403)

继承 ForbiddenError,表示权限验证失败。

错误类默认消息
LoginErrorInvalid password for user {0}.
BuiltinLoginErrorBuiltin login is disabled.
AccessDeniedErrorAccess denied.
InvalidTokenErrorThe {0} Token is invalid.
BlacklistedErrorAddress or user {0} is blacklisted.
VerifyPasswordErrorPasswords don't match.
OpcountExceededErrorToo frequent operations of {0} (limit: {2} operations in {1} seconds).
PermissionErrorYou don't have the required permission ({0}) in this domain. 动态
PrivilegeErrorYou don't have the required privilege. 动态
CurrentPasswordErrorCurrent password doesn't match.

PermissionError:若 params[0]bigint 权限标志,自动替换为对应的权限描述文本。

PrivilegeError:若缺少 PRIV_USER_PROFILE,消息变为 "You're not logged in."

User / Domain Errors (403)

继承 ForbiddenError,表示用户或域操作冲突。

错误类默认消息
UserAlreadyExistErrorUser {0} already exists.
RoleAlreadyExistErrorThis role already exists.
DomainAlreadyExistsErrorThe domain {0} already exists.
DomainJoinForbiddenErrorYou are not allowed to join domain {0}. {1}
DomainJoinAlreadyMemberErrorFailed to join the domain. You are already a member.
InvalidJoinInvitationCodeErrorThe invitation code you provided is invalid.
AlreadyVotedErrorYou've already voted.

Contest / Homework Errors (403)

继承 ForbiddenError,表示比赛/作业相关业务规则违反。

错误类默认消息
ContestNotAttendedErrorYou haven't attended this contest yet.
ContestAlreadyAttendedErrorYou've already attended this contest.
ContestNotLiveErrorThis contest is not live.
ContestNotEndedErrorThis contest is not ended.
ContestScoreboardHiddenErrorContest scoreboard is not visible.
HomeworkNotLiveErrorThis homework is not open.
HomeworkNotAttendedErrorYou haven't claimed this homework yet.

Training Errors (403)

继承 ForbiddenError

错误类默认消息
TrainingAlreadyEnrollErrorYou've already enrolled this training.

Problem / File Errors (403)

继承 ForbiddenError,表示题目或文件操作被拒绝。

错误类默认消息
NotAssignedErrorYou are not assigned to this {0}.
FileLimitExceededErrorFile {0} limit exceeded.
FileUploadErrorFile upload failed.
FileExistsErrorFile {0} already exists.
HackFailedErrorHack failed: {0}
ProblemAlreadyExistErrorProblem {0} already exists.
ProblemAlreadyUsedByContestErrorProblem {0} is already used by contest {1}.
ProblemNotAllowPretestErrorPretesting is not supported for {0}.
ProblemNotAllowLanguageErrorThis language is not allowed to submit.
ProblemNotAllowCopyErrorYou are not allowed to copy this problem from {0} to {1}.
DiscussionLockedErrorThe discussion is locked, you can not reply anymore.
RequireProErrorRequireProError

Validation / Logic Errors (400)

继承 BadRequestError,表示请求参数或业务逻辑无效。

错误类默认消息
PretestRejudgeFailedErrorCannot rejudge a pretest record.
HackRejudgeFailedErrorCannot rejudge a hack record.
CannotDeleteSystemDomainErrorYou are not allowed to delete system domain.
OnlyOwnerCanDeleteDomainErrorYou are not the owner of this domain.
CannotEditSuperAdminErrorYou are not allowed to edit super admin in web.
ProblemConfigErrorInvalid problem config.
ProblemIsReferencedErrorCannot {0} of a referenced problem.
AuthOperationError{0} is already {1}.
NotLaunchedByPM2ErrorNot launched by PM2.

Not Found Errors (404)

继承 NotFoundError,表示资源不存在。

错误类默认消息
UserNotFoundErrorUser {0} not found.
NoProblemErrorNo problem.
RecordNotFoundErrorRecord {0} not found.
ProblemDataNotFoundErrorData of problem {0} not found.
MessageNotFoundErrorMessage {0} not found.
DocumentNotFoundErrorDocument {2} not found.

Document Sub-type Not Found (404)

继承 DocumentNotFoundError(间接继承 NotFoundError),表示特定类型的文档不存在。

错误类默认消息
ProblemNotFoundErrorProblem {1} not found.
SolutionNotFoundErrorSolution {1} not found.
TrainingNotFoundErrorTraining {1} not found.
ContestNotFoundErrorContest {1} not found.
DiscussionNotFoundErrorDiscussion {1} not found.
DiscussionNodeNotFoundErrorDiscussion node {1} not found.

继承关系:

NotFoundError
└── DocumentNotFoundError ("Document {2} not found.")
    ├── ProblemNotFoundError ("Problem {1} not found.")
    ├── SolutionNotFoundError ("Solution {1} not found.")
    ├── TrainingNotFoundError ("Training {1} not found.")
    ├── ContestNotFoundError ("Contest {1} not found.")
    ├── DiscussionNotFoundError ("Discussion {1} not found.")
    └── DiscussionNodeNotFoundError ("Discussion node {1} not found.")