AlistGo/alist · error

wukong upload to tos failed: code=%d message=%s

Error message

wukong upload to tos failed: code=%d message=%s

What it means

Thrown by uploadToTOS after POSTing the file body directly to https://<host>/upload/v1/<storeURI>. The TOS upload endpoint responded with a code other than 2000 (minUploadSubmitSuccess). The storage layer (Volcengine TOS fronted by Wukong) rejected the transfer — commonly auth, expiry, or host issues.

Source

Thrown at drivers/wukong/driver.go:589

		SetHeader("Host", host).
		SetHeader("Referer", webReferer).
		SetHeader("Origin", "https://pan.wkbrowser.com").
		SetHeader("Authorization", auth).
		SetHeader("Content-Type", "application/octet-stream").
		SetHeader("Content-Crc32", crc32Hex).
		SetHeader("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, url.QueryEscape(fileName))).
		SetHeader("Content-Length", strconv.FormatInt(size, 10)).
		SetBody(body).
		SetResult(&resp)
	if storageUser != "" {
		req.SetHeader("X-Storage-U", storageUser)
	}
	_, err := req.Post(uploadURL)
	if err != nil {
		return err
	}
	if resp.Code != minUploadSubmitSuccess {
		return fmt.Errorf("wukong upload to tos failed: code=%d message=%s", resp.Code, resp.Message)
	}
	if resp.Data.Crc32 != "" && !strings.EqualFold(resp.Data.Crc32, crc32Hex) {
		return fmt.Errorf("wukong upload to tos crc32 mismatch: local=%s remote=%s", crc32Hex, resp.Data.Crc32)
	}
	return nil
}

func (d *Wukong) uploadToTOSMultipart(ctx context.Context, host, storeURI, auth, storageUser string, tempFile model.File, size int64, up driver.UpdateProgress) error {
	uploadID, err := d.initMultipartUpload(ctx, host, storeURI, auth, storageUser)
	if err != nil {
		return err
	}

	totalParts := int((size + multipartChunkSize - 1) / multipartChunkSize)
	if totalParts <= 0 {
		return errors.New("invalid multipart parts")
	}
	parts := make([]string, 0, totalParts)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Retry via the multipart path (uploadToTOSMultipart) or re-run applyUploadInner to get fresh auth and hosts
  2. Ensure storageUser is set on the request when provided by ApplyUploadInner
  3. Confirm Content-Length matches the exact byte count being sent
  4. If resp.Message shows auth/expiry, mint a new auth token and restart the TOS transfer
Defensive patterns

Strategy: retry

Try / catch

if err := d.uploadToTOS(ctx, host, storeURI, auth, storageUser, tempFile, size); err != nil {
    if strings.Contains(err.Error(), "auth") || strings.Contains(err.Error(), "expire") {
        // re-apply for fresh auth, then retry once
        return d.restartAndUpload(ctx)
    }
    return err
}

Prevention

When it happens

Trigger: Authorization header (from ApplyUploadInner) expired during a slow upload; X-Storage-U missing when storageUser required; upload host from candidates unreachable/decommissioned; Content-Length/Content-Disposition malformed; body truncated.

Common situations: Large single-request uploads exceeding token validity; best-host selection picking a dead node (ClientBestHosts fallback not exercised); proxy or CDN in front mangling headers.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/741864c20944f3af. Report an issue: GitHub.