yikart/AiToEarn · error · AppException

VideoUploadVidNotFound

VideoUploadVidNotFound

Error message

VideoUploadVidNotFound

What it means

downloadUrlAndUploadAsStream 在调用 uploadMaterial 成功后,期望上传结果 uploadResult.Data.Vid 存在;若火山 VOD 返回的 Result 中没有 Vid,则抛出 VideoUploadVidNotFound,表示上传链路完成但未得到媒体 ID。

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/libs/volcengine/services/upload.service.ts:230

    this.logger.debug({
      fileName,
      fileExtension,
      fileSize,
      url,
    }, '[downloadUrlAndUploadAsStream] 准备上传')

    const uploadResult = await this.uploadMaterial({
      SpaceName: this.config.spaceName,
      Content: response.data,
      FileSize: fileSize,
      FileName: fileName,
      FileExtension: fileExtension,
    })

    const vid = uploadResult.Data?.Vid
    if (!vid) {
      throw new AppException(ResponseCode.VideoUploadVidNotFound)
    }

    return vid
  }

  /**
   * 批量上传 URL 并获取 vids
   * 使用下载后流式上传的方式,比 URL 批量拉取更快
   */
  async batchUploadUrlsAndGetVids(
    urlInputs: Array<{ url: string, options?: VideoUrlInput }>,
  ): Promise<string[]> {
    const results = await Promise.allSettled(
      urlInputs.map(({ url, options }, index) =>
        this.downloadUrlAndUploadAsStream(url, options)
          .then((vid): UploadSuccess => ({ success: true, vid, url, index }))
          .catch((error): UploadFailure => {
            const errorMessage = getErrorMessage(error)

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. 记录 uploadResult 完整内容确认 Data 是否存在及结构。
  2. 核对 config.spaceName 与火山 VOD 控制台中的空间名一致且已开通。
  3. 确认上传 Functions 配置(GetMeta/AddOptionInfo)未被裁剪。
  4. 检查 @volcengine/openapi SDK 版本是否与响应结构匹配,必要时升级或降级。

Example fix

// before
const vid = await uploadService.downloadUrlAndUploadAsStream(url)
// after
let vid: string
try {
  vid = await uploadService.downloadUrlAndUploadAsStream(url)
} catch (e) {
  if ((e as any)?.code === ResponseCode.VideoUploadVidNotFound) {
    logger.error({ spaceName: process.env.VOLCSPACE_NAME }, 'Upload ok but no Vid; check VOD space config')
  }
  throw e
}
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.VOLCSPACE_NAME) throw new Error('VOLCSPACE_NAME must be set')
// verify space exists once at startup via ListSpace or console check

Type guard

function hasVid(r: unknown): r is { Data: { Vid: string } } {
  return r != null && typeof r === 'object'
    && typeof (r as any).Data?.Vid === 'string' && (r as any).Data.Vid.length > 0
}

Try / catch

try {
  vid = await downloadUrlAndUploadAsStream(url)
} catch (e) {
  if ((e as any)?.code === ResponseCode.VideoUploadVidNotFound) {
    logger.error({ spaceName: config.spaceName }, 'No Vid returned; verify VOD space and SDK response shape')
  }
  throw e
}

Prevention

When it happens

Trigger: UploadMaterial 响应无 Error 但 Data.Vid 缺失:SpaceName 配置错误/不存在、GetMeta Function 未返回媒体信息、响应结构变化、上传的实际上下文被 VOD 接受但未生成媒体记录。

Common situations: VOLCSPACE_NAME 环境变量指向错误或未初始化的空间;火山 VOD 服务未在该空间开通媒体上传;SDK 升级后 Result.Data 结构改变;上传了非视频内容导致无 Vid。

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/4f407dc9dbd5b17b. Report an issue: GitHub.