ErrorTable.kt

// Generated by tools/gen-errors.mjs from spec/errors.json version 2026-10-08. Do not edit.
package com.shengzhiai.yugu.errors

/** Error, warning and local code tables. */
object ErrorTable {
    data class Entry(
        val code: Int,
        val name: String,
        val category: String,
        val retryable: Boolean,
        val http: Int,
        val message: String,
    )

    val ERRORS: Map<Int, Entry> = listOf(
        Entry(40001, "VALIDATION_ERROR", "INVALID_PARAM", false, 400, "请求参数校验失败"),
        Entry(40100, "UNAUTHORIZED", "AUTH", false, 401, "未认证,缺少或无效的凭据"),
        Entry(40300, "FORBIDDEN", "PERMISSION", false, 403, "无权限,例如 API Key 未授权该 coreType"),
        Entry(40400, "NOT_FOUND", "NOT_FOUND", false, 404, "资源不存在"),
        Entry(40900, "CONFLICT", "CONFLICT", false, 409, "资源冲突"),
        Entry(40901, "IDEMPOTENCY_IN_PROGRESS", "CONFLICT", true, 409, "同一幂等键的请求仍在处理中,稍后用同一个键重试"),
        Entry(40902, "QUOTA_INSUFFICIENT", "QUOTA", false, 409, "套餐额度和账户余额均不足"),
        Entry(40903, "IDEMPOTENCY_KEY_REUSED", "CONFLICT", false, 409, "幂等键已用于另一个不同的请求"),
        Entry(42900, "TOO_MANY_REQUESTS", "RATE_LIMIT", true, 429, "请求过多或评测排队超时,按 Retry-After 稍后重试"),
        Entry(42901, "CONCURRENCY_LIMIT", "RATE_LIMIT", true, 429, "并发评测数超出套餐层级限制"),
        Entry(42902, "TRIAL_REPORT_DAILY_LIMIT", "QUOTA", false, 429, "试用层 AI 报告达到每日上限"),
        Entry(42903, "SANDBOX_DAILY_LIMIT", "QUOTA", false, 429, "沙箱密钥当日调用次数达到上限"),
        Entry(50000, "INTERNAL_ERROR", "SERVER", true, 500, "服务器内部错误"),
        Entry(50010, "FEATURE_NOT_IMPLEMENTED", "SERVER", false, 500, "功能未实现"),
        Entry(50200, "UPSTREAM_SERVICE_ERROR", "UPSTREAM", true, 502, "上游评测服务暂不可用"),
        Entry(2001, "TOKEN_EXPIRED", "AUTH", false, 401, "token 已过期,兼容层早期引擎接口也用此码表示缺少鉴权三元组或签名不匹配"),
        Entry(2002, "TOKEN_INVALID", "AUTH", false, 401, "token 无效,兼容层早期引擎接口也用此码表示时间戳超窗"),
        Entry(2003, "SIGNATURE_VERIFICATION_FAILED", "AUTH", false, 401, "签名验证失败,兼容层早期引擎接口也用此码表示 appKey 不存在"),
        Entry(2004, "SESSION_EXPIRED", "AUTH", false, 401, "会话已过期"),
        Entry(2005, "TOKEN_BLACKLISTED", "AUTH", false, 401, "token 已被列入黑名单"),
        Entry(2006, "API_KEY_INVALID", "AUTH", false, 401, "API Key 无效"),
        Entry(2007, "API_KEY_EXPIRED", "AUTH", false, 401, "API Key 已过期"),
        Entry(2008, "TOKEN_METADATA_NOT_FOUND", "AUTH", false, 401, "token 元数据丢失"),
        Entry(2009, "TOKEN_REFRESH_FAILED", "AUTH", false, 401, "token 刷新失败"),
        Entry(2010, "API_KEY_NOT_FOUND", "AUTH", false, 401, "API Key 不存在"),
        Entry(2011, "API_KEY_DISABLED", "AUTH", false, 401, "API Key 已禁用"),
        Entry(2012, "API_KEY_QUOTA_EXCEEDED", "QUOTA", false, 400, "API Key 配额已超限"),
        Entry(3001, "RATE_LIMIT_EXCEEDED_IP", "RATE_LIMIT", true, 429, "请求过于频繁,按来源地址限流"),
        Entry(3002, "RATE_LIMIT_EXCEEDED_USER", "RATE_LIMIT", true, 429, "请求过于频繁,按用户限流"),
        Entry(3003, "RATE_LIMIT_EXCEEDED_API_KEY", "RATE_LIMIT", true, 429, "请求过于频繁,按 API Key 限流"),
        Entry(1004, "USER_DISABLED", "PERMISSION", false, 400, "用户已禁用"),
        Entry(1005, "USER_LOCKED", "PERMISSION", false, 400, "用户已锁定"),
        Entry(1012, "ACCOUNT_DISABLED", "PERMISSION", false, 400, "账户已禁用"),
        Entry(1013, "ACCOUNT_FROZEN", "PERMISSION", false, 400, "账户已冻结"),
        Entry(1310, "ACCOUNT_BALANCE_INSUFFICIENT", "QUOTA", false, 400, "账户余额不足"),
        Entry(1311, "ACCOUNT_LEDGER_CONFLICT", "CONFLICT", true, 400, "账目并发冲突,重试即可"),
    ).associateBy { it.code }

    val WARNINGS: Map<Int, Entry> = listOf(
        Entry(1001, "NO_VALID_AUDIO", "AUDIO", false, 0, "No valid audio detected!"),
        Entry(1002, "VOLUME_TOO_LOW", "AUDIO", false, 0, "Audio volume too low!"),
        Entry(1003, "VOLUME_TOO_HIGH", "AUDIO", false, 0, "Audio volume too high!"),
        Entry(1004, "AUDIO_NOISY", "AUDIO", false, 0, "Audio noisy!"),
        Entry(1005, "AUDIO_INCOMPLETE", "AUDIO", false, 0, "Audio not complete!"),
        Entry(1009, "SCORER_DEGRADED", "AUDIO", true, 0, "scorer degraded"),
    ).associateBy { it.code }

    val LOCAL: Map<Int, Entry> = listOf(
        Entry(90001, "NETWORK_ERROR", "NETWORK", true, 0, "网络错误,连接失败或被重置"),
        Entry(90002, "TIMEOUT", "TIMEOUT", true, 0, "连接或读取超时"),
        Entry(90003, "CANCELLED", "CANCELLED", false, 0, "调用方取消了请求"),
        Entry(90004, "CLIENT_CLOSED", "STATE", false, 0, "客户端已关闭"),
        Entry(90005, "PROTOCOL_ERROR", "PROTOCOL", false, 0, "响应或帧无法解析"),
        Entry(90006, "RECONNECT_EXHAUSTED", "NETWORK", false, 0, "实时连接重连次数用尽"),
        Entry(90007, "RESULT_TIMEOUT", "TIMEOUT", true, 0, "结束后等待终评结果超时"),
        Entry(90008, "REPLAY_BUFFER_OVERFLOW", "STATE", false, 0, "重连重放缓冲超过上限"),
        Entry(90009, "INVALID_STATE", "STATE", false, 0, "当前会话状态不允许该操作"),
        Entry(90010, "INVALID_ARGUMENT", "INVALID_PARAM", false, 0, "调用参数不合法"),
        Entry(90011, "TLS_ERROR", "NETWORK", false, 0, "证书校验失败"),
        Entry(90101, "AUDIO_TOO_SHORT", "AUDIO", false, 0, "音频短于 1 秒"),
        Entry(90102, "AUDIO_TOO_LONG", "AUDIO", false, 0, "音频长于 300 秒,整段上传大于 50 MB,或实时评测一轮大于 10 MB"),
        Entry(90103, "AUDIO_SILENT", "AUDIO", false, 0, "音频全程静音"),
        Entry(90104, "AUDIO_LOW_VOLUME", "AUDIO", false, 0, "音量过低"),
        Entry(90105, "AUDIO_FORMAT_UNSUPPORTED", "AUDIO", false, 0, "不是 16 位 PCM 或采样率低于 16000"),
        Entry(90201, "RECORDER_PERMISSION_DENIED", "PERMISSION", false, 0, "没有麦克风权限"),
        Entry(90202, "RECORDER_UNAVAILABLE", "STATE", false, 0, "麦克风被占用或不可用"),
        Entry(90203, "RECORDER_ERROR", "STATE", false, 0, "录音过程出错"),
    ).associateBy { it.code }

    val HTTP_FALLBACK: Map<Int, String> = mapOf(
        400 to "INVALID_PARAM",
        401 to "AUTH",
        403 to "PERMISSION",
        404 to "NOT_FOUND",
        405 to "INVALID_PARAM",
        408 to "TIMEOUT",
        409 to "CONFLICT",
        413 to "INVALID_PARAM",
        415 to "INVALID_PARAM",
        422 to "INVALID_PARAM",
        425 to "RATE_LIMIT",
        429 to "RATE_LIMIT",
        500 to "SERVER",
        501 to "SERVER",
        502 to "UPSTREAM",
        503 to "UPSTREAM",
        504 to "UPSTREAM",
    )

    val RETRYABLE_HTTP: Set<Int> = setOf(408, 425, 429, 500, 502, 503, 504)
}

/** Named code constants. */
object ErrorCodes {
    const val VALIDATION_ERROR = 40001
    const val UNAUTHORIZED = 40100
    const val FORBIDDEN = 40300
    const val NOT_FOUND = 40400
    const val CONFLICT = 40900
    const val IDEMPOTENCY_IN_PROGRESS = 40901
    const val QUOTA_INSUFFICIENT = 40902
    const val IDEMPOTENCY_KEY_REUSED = 40903
    const val TOO_MANY_REQUESTS = 42900
    const val CONCURRENCY_LIMIT = 42901
    const val TRIAL_REPORT_DAILY_LIMIT = 42902
    const val SANDBOX_DAILY_LIMIT = 42903
    const val INTERNAL_ERROR = 50000
    const val FEATURE_NOT_IMPLEMENTED = 50010
    const val UPSTREAM_SERVICE_ERROR = 50200
    const val TOKEN_EXPIRED = 2001
    const val TOKEN_INVALID = 2002
    const val SIGNATURE_VERIFICATION_FAILED = 2003
    const val SESSION_EXPIRED = 2004
    const val TOKEN_BLACKLISTED = 2005
    const val API_KEY_INVALID = 2006
    const val API_KEY_EXPIRED = 2007
    const val TOKEN_METADATA_NOT_FOUND = 2008
    const val TOKEN_REFRESH_FAILED = 2009
    const val API_KEY_NOT_FOUND = 2010
    const val API_KEY_DISABLED = 2011
    const val API_KEY_QUOTA_EXCEEDED = 2012
    const val RATE_LIMIT_EXCEEDED_IP = 3001
    const val RATE_LIMIT_EXCEEDED_USER = 3002
    const val RATE_LIMIT_EXCEEDED_API_KEY = 3003
    const val USER_DISABLED = 1004
    const val USER_LOCKED = 1005
    const val ACCOUNT_DISABLED = 1012
    const val ACCOUNT_FROZEN = 1013
    const val ACCOUNT_BALANCE_INSUFFICIENT = 1310
    const val ACCOUNT_LEDGER_CONFLICT = 1311
    const val W_NO_VALID_AUDIO = 1001
    const val W_VOLUME_TOO_LOW = 1002
    const val W_VOLUME_TOO_HIGH = 1003
    const val W_AUDIO_NOISY = 1004
    const val W_AUDIO_INCOMPLETE = 1005
    const val W_SCORER_DEGRADED = 1009
    const val NETWORK_ERROR = 90001
    const val TIMEOUT = 90002
    const val CANCELLED = 90003
    const val CLIENT_CLOSED = 90004
    const val PROTOCOL_ERROR = 90005
    const val RECONNECT_EXHAUSTED = 90006
    const val RESULT_TIMEOUT = 90007
    const val REPLAY_BUFFER_OVERFLOW = 90008
    const val INVALID_STATE = 90009
    const val INVALID_ARGUMENT = 90010
    const val TLS_ERROR = 90011
    const val AUDIO_TOO_SHORT = 90101
    const val AUDIO_TOO_LONG = 90102
    const val AUDIO_SILENT = 90103
    const val AUDIO_LOW_VOLUME = 90104
    const val AUDIO_FORMAT_UNSUPPORTED = 90105
    const val RECORDER_PERMISSION_DENIED = 90201
    const val RECORDER_UNAVAILABLE = 90202
    const val RECORDER_ERROR = 90203
}