yikart/AiToEarn · error · Error
Video upload failed
Error message
Video upload failed
What it means
After a playlist insert (videos.insert/upload flow) the service checks response.data and throws a generic Error('Video upload failed') when the response body is falsy, i.e. Google returned 2xx without usable payload data. It is a weak success-check: the real cause is hidden and the console.error in the catch rethrows whatever preceded it.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/youtube/youtube.service.ts:1055
// 调用 YouTube API 上传视频
const response = await this.youtubeService.playlistItems.insert(
{
auth: oauth2Client,
part: 'snippet,status, id, contentDetails',
requestBody
}
);
// const response = { "data": {
// "id": "7RckZHFBu7A"
// },}
// 返回上传的视频 ID
if (response.data) {
console.log('Playlist insert successfully:', response.data);
return response.data;
} else {
throw new Error('Video upload failed');
}
} catch (error) {
console.error('Error uploading video:', error);
throw error;
}
}
/**
* 获取播放列表项。
*/
async getPlayItemsList(accessToken, playlistId, itemsIds, maxResults, pageToken) {
// 设置 OAuth2 客户端凭证
this.oauth2Service.setCredentials(accessToken);
const oauth2Client = this.oauth2Service.getClient();
// 根据传入的参数来选择一个有效的请求参数View on GitHub (pinned to d3aa8bea5b)
Solutions
- Log the full response (status, headers, body) before this check to see why data is missing.
- Verify the upload request builds correct metadata (snippet, status) and required parts.
- Check token validity and quota (upload quota 403/412) — a failed call may surface as empty data.
- Add explicit response.status check (e.g. require 200/201) and include status in the thrown message.
- Retry the upload once after confirming network/proxy stability.
Example fix
// before
if (response.data) { return response.data; } else { throw new Error('Video upload failed'); }
// after
if (response.status === 200 && response.data?.id) { return response.data; }
throw new Error(`Video upload failed: status=${response.status} body=${JSON.stringify(response.data)}`); Defensive patterns
Strategy: try-catch
Validate before calling
if (!response || typeof response.status !== 'number') throw new Error('No response received from YouTube API'); Type guard
function hasUploadPayload(res: { status?: number; data?: { id?: string } | null }): res is { status: number; data: { id: string } } {
return typeof res.status === 'number' && !!res.data && typeof res.data.id === 'string';
} Try / catch
try {
const result = await client.uploadVideo(accountId, file);
if (!result?.id) throw new Error(`Upload returned no id: ${JSON.stringify(result)}`);
} catch (error) {
console.error('Upload failed:', { status: error?.response?.status, data: error?.response?.data, message: error?.message });
// retry once with backoff for transient/network errors, then surface details
} Prevention
- Log full response status+body at the throw site for diagnosability.
- Check response.status and data.id, not truthiness of data alone.
- Confirm quota and token validity before large uploads.
- Add a bounded retry with backoff for transient failures.
When it happens
Trigger: The YouTube API call resolves but response.data is undefined/null/empty object; network proxies or retry layers returning empty 2xx bodies; upstream error thrown earlier and rethrown through this catch with this message logged context.
Common situations: Rate-limited or flaky networks producing empty responses; misconfigured request part/body so the API returns 204/no content; stale tokens causing an earlier failure that surfaces only through the generic catch.
Related errors
- No image generated
- VideoUploadVidNotFound
- Relay uploadSign returned no uploadUrl: ${JSON.stringify(sig
- ChannelPlatformResponseInvalid
- ChannelPlatformMediaProcessingFailed
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/05fa104b51b7c5ae.
Report an issue: GitHub.