yikart/AiToEarn · error · AppException
AiCallFailed
AiCallFailed
Error message
AiCallFailed
What it means
volcengine.service.ts 的通用 checkApiResponseError 会检查所有 VOD API 响应:当 ResponseMetadata.Error 存在时,把火山原始错误 Code/Message 包装为 AiCallFailed 抛出。这是所有火山 OpenAPI 业务级错误在库内的统一出口。
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/libs/volcengine/volcengine.service.ts:352
serviceName: 'vod',
})
}
/**
* 检查 API 响应中的错误并抛出异常(内部方法)
*/
private checkApiResponseError<T>(
response: OpenApiResponse<T>,
operation: string,
requestData?: unknown,
): asserts response is OpenApiResponse<T> & { Result: T } {
if (response.ResponseMetadata?.Error) {
const error = response.ResponseMetadata.Error
this.logger.error(
{ error, requestData },
`${operation} failed: ${error.Code || 'Unknown'} - ${error.Message}`,
)
throw new AppException(ResponseCode.AiCallFailed, {
code: error.Code || 'Unknown',
message: error.Message,
})
}
if (!response.Result) {
this.logger.error({ requestData }, `${operation} returned no result`)
throw new AppException(ResponseCode.AiCallFailed, {
message: typeof response === 'string' ? response : 'No result returned',
})
}
}
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- 解析异常中的 code/message(原始火山错误码),按码定位:SignatureDoesNotMatch→检查密钥、InvalidParameter→修参数、RequestLimitExceeded→退避重试。
- 核对 VolcengineConfig 注入的 accessKeyId/secretAccessKey/spaceName 是否为当前有效值。
- 确认对应火山服务已在控制台开通且地域正确。
- 对可重试错误码实现指数退避重试。
Example fix
// before
const res = await volcengineService.getUploadTaskInfo(req)
// after
try {
const res = await volcengineService.getUploadTaskInfo(req)
} catch (e) {
const { code, message } = (e as any).data ?? {}
logger.error({ code, message }, 'Volcengine API failed')
if (RETRYABLE_CODES.includes(code)) return retryWithBackoff(() => volcengineService.getUploadTaskInfo(req))
throw e
} Defensive patterns
Strategy: try-catch
Validate before calling
for (const k of ['VOLC_ACCESS_KEY_ID', 'VOLC_SECRET_ACCESS_KEY', 'VOLCSPACE_NAME']) {
if (!process.env[k]) throw new Error(`Missing Volcengine env var: ${k}`)
} Type guard
function isVolcengineApiError(e: unknown): e is AppException & { data: { code: string, message: string } } {
return e instanceof AppException
&& (e as any).code === ResponseCode.AiCallFailed
&& typeof (e as any).data?.code === 'string'
} Try / catch
try {
return await volcengineService.someOperation(req)
} catch (e) {
if (isVolcengineApiError(e)) {
const { code, message } = e.data
if (RETRYABLE.includes(code)) return retryWithBackoff(() => volcengineService.someOperation(req))
throw new Error(`Volcengine ${code}: ${message}`)
}
throw e
} Prevention
- 维护火山错误码→处理策略(重试/失败/告警)映射表
- 密钥轮换后立即更新配置并做签名连通性自检
- 确认服务与空间在火山控制台已开通且地域一致
- 对所有可重试错误码实现指数退避
When it happens
Trigger: 任何经 volcengineService(submitDirectEditTaskAsync、getDirectEditResult、uploadMediaByUrl、uploadMaterial、getUploadTaskInfo 等)的调用返回带 ResponseMetadata.Error 的响应:签名错误、权限不足、参数非法、限流、空间不存在、内部错误等。
Common situations: AK/SK 配错或轮换后未更新;未开通 VOD/智能剪辑服务;SpaceName 不存在;请求参数不符合 API 版本 2018-01-01 规范;火山侧限流或故障。
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/6da136a887739e2b.
Report an issue: GitHub.