yikart/AiToEarn · warning · Error

Canvas not provided and no vid:// video source found in Trac

Error message

Canvas not provided and no vid:// video source found in Track. Please provide Canvas dimensions or use vid:// video sources.

What it means

getVideoDetail requires both videoId and accountId query parameters. Either missing triggers BadRequestException('videoId和accountId是必须的'). accountId is needed to resolve the stored user access token, videoId identifies the video to fetch.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/volcengine/video-edit.mcp.ts:55

  ): Promise<{ Width: number, Height: number }> {
    if (canvas) {
      return canvas
    }

    let vid: string | undefined
    for (const layer of track) {
      for (const element of layer) {
        if (element.Type === 'video' && element.Source?.startsWith('vid://')) {
          vid = element.Source.replace('vid://', '')
          break
        }
      }
      if (vid)
        break
    }

    if (!vid) {
      throw new Error('Canvas not provided and no vid:// video source found in Track. Please provide Canvas dimensions or use vid:// video sources.')
    }

    const mediaInfos = await this.volcengineService.getMediaInfos({ Vids: vid })
    const sourceInfo = mediaInfos.MediaInfoList?.[0]?.SourceInfo

    if (!sourceInfo?.Width || !sourceInfo?.Height) {
      throw new Error(`Canvas not provided and failed to retrieve video dimensions for vid://${vid}. Please provide Canvas dimensions explicitly.`)
    }

    return { Width: sourceInfo.Width, Height: sourceInfo.Height }
  }

  /**
   * 提交视频编辑任务(直接使用 Track 结构)
   */
  createSubmitDirectEditTaskTool(userId: string, userType: UserType) {
    return wrapTool(
      this.logger,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Include both ?videoId=<id>&accountId=<id> in the request.
  2. Persist the accountId alongside video references in the client so detail views always have it.
  3. Validate both params client-side before navigating to the detail route.

Example fix

// before
await api.get(`/plat/tiktok/video/${videoId}`);
// after
await api.get(`/plat/tiktok/video/${videoId}?accountId=${encodeURIComponent(accountId)}`);
Defensive patterns

Strategy: validation

Validate before calling

if (!videoId || !accountId) throw new Error('videoId和accountId是必须的');
await api.get(`/plat/tiktok/video/${videoId}`, { params: { accountId } });

Type guard

function isVideoDetailQuery(v): v is { videoId: string; accountId: string } {
  return typeof v?.videoId === 'string' && v.videoId.length > 0 && typeof v?.accountId === 'string' && v.accountId.length > 0;
}

Try / catch

try {
  return await api.get(`/plat/tiktok/video/${videoId}`, { params: { accountId } });
} catch (e) {
  if (e.response?.status === 400) console.warn('缺少videoId/accountId,跳过详情加载');
  throw e;
}

Prevention

When it happens

Trigger: GET the video-detail route where ?videoId= or ?accountId= (or both) are absent or empty strings.

Common situations: Deep link built from a video list omits the account context, or a stale cached video entry no longer carries the originating accountId.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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