yikart/AiToEarn · error · Error
上传封面失败,失败原因:
Error message
上传封面失败,失败原因:
What it means
After uploading cover data, the service checks uploadPartRes.ETag; if absent it throws '上传封面失败,失败原因:' + X-Errno. Missing ETag means the server did not accept the part upload. Note a bug: the string concatenation binds before ||, so when X-Errno is missing the expression evaluates to the truthy prefix string and '未知错误' is never used.
Source
Thrown at project/aitoearn-electron/electron/plat/shipinhao/index.ts:845
const uploadId = uploadIdRes.UploadID;
// 开始上传
const uploadPartRes = await this.uploadFile(
this.uploadpartdfsUrl +
`?UploadID=${uploadId}&PartNumber=1&QuickUpload=2`,
fileData,
{
Authorization: uploadParams.authKey,
'X-Arguments': uploadArgumentsString,
'Content-Type': 'application/octet-stream',
},
undefined,
proxy,
);
if (!uploadPartRes.ETag) {
throw new Error(
'上传封面失败,失败原因:' + uploadPartRes.data?.['X-Errno'] ||
'未知错误',
);
}
// 上传成功
const uploadPartInfo = [
{
PartNumber: 1,
ETag: uploadPartRes.ETag,
},
];
// 完成分片上传
const uploadCompleteRes = await this.uploadFile(
this.uploadCompleteUrl + `?UploadID=${uploadId}`,
Buffer.from(
JSON.stringify({View on GitHub (pinned to d3aa8bea5b)
Solutions
- Read the X-Errno value from the response data to identify the COS rejection reason.
- Re-request upload params and retry the cover upload from scratch.
- Validate the cover image file (exists, non-empty, correct format) before upload.
- Fix the operator-precedence bug so '未知错误' shows when X-Errno is absent: wrap the concatenation in parentheses.
Example fix
// before
throw new Error(
'上传封面失败,失败原因:' + uploadPartRes.data?.['X-Errno'] ||
'未知错误',
);
// after
throw new Error(
'上传封面失败,失败原因:' + (uploadPartRes.data?.['X-Errno'] ?? '未知错误'),
); Defensive patterns
Strategy: type-guard
Validate before calling
import fs from 'fs';
if (!fs.existsSync(coverPath) || fs.statSync(coverPath).size === 0) {
throw new Error('invalid cover file');
} Type guard
function hasETag(res: unknown): res is { ETag: string } {
return typeof (res as any)?.ETag === 'string' && (res as any).ETag.length > 0;
} Try / catch
try {
await service.uploadCoverFile(/*...*/);
} catch (e) {
if (e.message.includes('上传封面失败')) {
const errno = e.message.split('失败原因:')[1];
console.error('cover part upload rejected, X-Errno:', errno);
}
} Prevention
- Check ETag on every part response before proceeding to complete
- Note the operator-precedence bug: 'prefix' + x || y never yields y — use parentheses
- Refresh upload params if the session may have expired mid-flow
- Validate image integrity before sending bytes
When it happens
Trigger: uploadCoverFile → part-upload (uploadFile) response without ETag: COS rejecting the chunk due to bad signature, wrong Content-MD5, session expiry, or an error body in data['X-Errno'].
Common situations: Expired upload session between apply and part upload, corrupted cover file bytes, proxy interrupting the PUT, or COS returning X-Errno (e.g. signature mismatch) instead of ETag.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/ca582252f244c6d2.
Report an issue: GitHub.