yikart/AiToEarn · error · AppException
AiCallFailed
AiCallFailed
Error message
任务结果为空
What it means
Volcengine DirectEdit 的 getDirectEditResult 调用 GetDirectEditResult 后,processDirectEditResult 收到的 response.Result 为 null/undefined。库把『结果整体缺失』视为 AI 调用失败并抛出 AiCallFailed,而空数组被视为『任务处理中』返回 Processing 状态。也就是说,结果缺失(而不是结果未准备好)被认为是真正的异常。
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/libs/volcengine/services/direct-edit.service.ts:80
this.checkApiResponseError(response, 'Submit direct edit task', requestData)
return response.Result
}
/**
* 处理剪辑任务查询结果
* @param result API 返回的原始结果
* @param reqId 请求的任务 ID
* @returns 处理后的任务结果
*/
private processDirectEditResult(
result: GetDirectEditResultResponse | null | undefined,
reqId: string,
): GetDirectEditResultItem {
// 处理空结果
if (!result) {
this.logger.error({ reqId }, '[ProcessDirectEditResult] Result 为空')
throw new AppException(ResponseCode.AiCallFailed, '任务结果为空')
}
// 如果 Result 是数组
if (Array.isArray(result)) {
if (result.length === 0) {
// 任务刚提交,火山引擎还没准备好数据,返回处理中状态
this.logger.debug({ reqId }, '[ProcessDirectEditResult] 任务结果为空数组,任务可能刚提交还在准备中')
return {
TaskId: reqId,
ReqId: reqId,
Application: 'VideoTrackToB',
Status: 'Processing',
}
}
return result[0]
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- 打印 reqId 和完整响应体,确认 Result 确实缺失而不是类型断言错误。
- 核对 ReqId 是否来自同一次 SubmitDirectEditTaskAsync 的返回且 SpaceName 一致。
- 对『任务刚提交』的场景重试查询:空数组会返回 Processing,但 null 不行,需要调用方自行重试。
- 若持续为空,登录火山 VOD 控制台按 ReqId/TaskId 查任务是否仍存在。
Example fix
// before
const item = await directEditService.getDirectEditResult({ ReqIds: [reqId] })
// after
let item: GetDirectEditResultItem | null = null
for (let i = 0; i < 5; i++) {
try {
item = await directEditService.getDirectEditResult({ ReqIds: [reqId] })
break
} catch (e) {
if (isAiCallFailed(e) && e.message === '任务结果为空') {
await sleep(3000)
continue
}
throw e
}
}
if (!item) throw new Error(`Direct edit result unavailable for ${reqId}`) Defensive patterns
Strategy: retry
Validate before calling
if (!reqId || typeof reqId !== 'string') throw new Error('Valid ReqId required before polling GetDirectEditResult') Type guard
function hasDirectEditResult(r: unknown): r is { Result: unknown[] | object } {
return r != null && typeof r === 'object' && 'Result' in r && r.Result != null
} Try / catch
try {
const item = await getDirectEditResult({ ReqIds: [reqId] })
if (item.Status === 'Processing') return scheduleRetry(reqId)
} catch (e) {
if (isAiCallFailed(e) && e.message === '任务结果为空') return scheduleRetry(reqId)
throw e
} Prevention
- 提交任务后等待数秒再首次查询,并对空结果做有限次退避重试
- 保存并核对 SubmitDirectEditTaskAsync 返回的 ReqId 与查询用 ID 一致
- 为轮询设置最大尝试次数和超时,避免无限轮询
- 监控该错误日志中的 reqId,定位是无效 ID 还是服务端延迟
When it happens
Trigger: 调用 getDirectEditResult({ ReqIds: [...] }) 时,火山引擎 VOD API 返回了无 Error 的响应但 Result 字段为 null/undefined:例如 ReqId 无效或已过期、任务在火山侧被删除、响应被网关截断,或 Result 缺少 Result 字段。
Common situations: 在任务提交后过早且只查了一次就假设有结果;ReqId 拼写错误或来自另一个 SpaceName;火山引擎返回了 200 但 body 结构与 SDK 类型不符(API 版本变更);代理/网关剥掉了字段。
Related errors
- AiCallFailed
- AiCallFailed
- AiCallFailed
- image_tail requires a single first frame image
- content is required
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/ccf6f8d98130276a.
Report an issue: GitHub.