flipped-aurora/gin-vue-admin · error
分片不全: %d/%d
Error message
分片不全: %d/%d
What it means
Complete finalizes a chunked upload: it counts recorded MediaUploadChunk rows for the upload session and compares to the session's ChunkTotal. If fewer chunks are recorded than expected it returns "分片不全: %d/%d" (chunks incomplete: got/total) via the fail() path without merging. Note the Count error is ignored, so this message also fires when the count query itself fails.
Source
Thrown at server/service/media/media_upload.go:130
Where("id = ? AND status = ?", uploadID, media.UploadStatusUploading).
Update("status", media.UploadStatusMerging)
if res.Error != nil {
return m, res.Error
}
if res.RowsAffected == 0 {
return m, errors.New("上传不在可合并状态(可能已在合并或已完成)")
}
fail := func(e error) (media.FileUploadAndDownload, error) {
global.GVA_DB.WithContext(ctx).Model(&media.MediaUpload{}).Where("id = ?", uploadID).Update("status", media.UploadStatusFailed)
return m, e
}
// 校验分片齐全
var cnt int64
global.GVA_DB.WithContext(ctx).Model(&media.MediaUploadChunk{}).Where("upload_id = ?", uploadID).Count(&cnt)
if int(cnt) != up.ChunkTotal {
return fail(fmt.Errorf("分片不全: %d/%d", cnt, up.ChunkTotal))
}
// 合并到临时成品
merged := filepath.Join(upload.ChunkDir(uploadID), "merged.bin")
gotMd5, err := upload.MergeChunks(uploadID, up.ChunkTotal, merged)
if err != nil {
return fail(err)
}
if gotMd5 != up.FileHash {
return fail(errors.New("整文件校验失败"))
}
// 经 OSS 接口推到配置存储
fh, cleanup, err := upload.BuildFileHeader(merged, "file", up.FileName)
if err != nil {
return fail(err)
}
defer cleanup()View on GitHub (pinned to 3136500ef3)
Solutions
- List uploaded chunk indexes and upload only the missing ones, then call Complete again
- Fix client logic to await all chunk PUTs (Promise.all) before calling Complete
- Handle chunk-level failures: any chunk rejected (e.g. hash mismatch) must be retried before Complete
- Confirm the client uses the same uploadID returned at session creation for every chunk and the Complete call
- Investigate DB errors if all chunks were actually uploaded — the Count error is ignored, so a DB outage surfaces as this message
Example fix
// before chunks.forEach(c => upload(c)) await complete(uploadId) // after await Promise.all(chunks.map(c => upload(c))) await complete(uploadId)
Defensive patterns
Strategy: validation
Validate before calling
// client: verify all chunks acknowledged before completing
const acked = await listUploadedChunks(uploadId)
if (acked.length !== chunkTotal) {
const missing = diff(range(chunkTotal), acked)
await Promise.all(missing.map(i => uploadChunk(uploadId, i)))
} Try / catch
if err := svc.Complete(ctx, uploadID, meta); err != nil {
if strings.Contains(err.Error(), "分片不全") {
// parse got/total, re-upload missing chunk indexes, then retry Complete
return reconcileAndComplete(uploadID)
}
return err
} Prevention
- Await all parallel chunk uploads before calling Complete
- Track per-chunk ACKs and retry failures (including hash rejections) before completing
- Use a single uploadID consistently for all chunks and Complete
- On the server, check the Count() error instead of ignoring it so DB outages aren't masked as missing chunks
When it happens
Trigger: Calling Complete before all chunks have been uploaded (some indexes never sent), a chunk rejected by MD5 validation (error 438) leaving a gap, chunks written to a different uploadID, or a DB error making Count return 0 — all raise this from media_upload.go:130.
Common situations: Frontend firing Complete optimistically before the last parallel chunk request resolves; a failed/corrupt chunk silently skipped by the client; retries creating a new uploadID while Complete uses the old one; DB connectivity issues causing a zero count (error swallowed).
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/fa009266d00cd095.
Report an issue: GitHub.