juicedata/juicefs · error

No ETag

Error message

No ETag

What it means

ufile.UploadPart expects the UCloud UFile response to carry an ETag header for each uploaded part; the ETag is required to complete the multipart upload. If the response has no Etag header, the part result cannot be built and the upload fails.

Source

Thrown at pkg/object/ufile.go:300

	}
	return &MultipartUpload{UploadID: out.UploadId, MinPartSize: int64(out.BlkSize), MaxCount: 1000000}, nil
}

func (u *ufile) UploadPart(ctx context.Context, key string, uploadID string, num int, data []byte) (*Part, error) {
	// UFile require the PartNumber to start from 0 (continuous)
	num--
	path := fmt.Sprintf("%s?uploadId=%s&partNumber=%d", key, uploadID, num)
	resp, err := u.request(ctx, "PUT", path, bytes.NewReader(data), nil)
	if err != nil {
		return nil, err
	}
	defer cleanup(resp)
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("UploadPart: %s", parseError(resp).Error())
	}
	etags := resp.Header["Etag"]
	if len(etags) < 1 {
		return nil, errors.New("No ETag")
	}
	return &Part{Num: num, Size: len(data), ETag: strings.Trim(etags[0], "\"")}, nil
}

func (u *ufile) AbortUpload(ctx context.Context, key string, uploadID string) {
	_, _ = u.request(ctx, "DELETE", key+"?uploads="+uploadID, nil, nil)
}

func (u *ufile) CompleteUpload(ctx context.Context, key string, uploadID string, parts []*Part) error {
	etags := make([]string, len(parts))
	for i, p := range parts {
		etags[i] = p.ETag
	}
	resp, err := u.request(ctx, "POST", key+"?uploadId="+uploadID, bytes.NewReader([]byte(strings.Join(etags, ","))), nil)
	if err != nil {
		return err
	}
	defer cleanup(resp)

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Verify the bucket's domain/endpoint points directly at UFile and no proxy strips the Etag header
  2. Re-run the upload; transient gateway issues may drop headers
  3. Check response with curl to confirm the Etag header is present at your endpoint
  4. Capture the raw HTTP response for debugging and report to UFile support if the service omits ETag
Defensive patterns

Strategy: retry

Validate before calling

resp, _ := http.Head(endpoint)
if resp.Header.Get("Etag") == "" {
	// endpoint/proxy strips headers — fix config before uploading
}

Try / catch

part, err := store.UploadPart(ctx, key, uploadID, num, data)
if err != nil && strings.Contains(err.Error(), "No ETag") {
	// retry once; else fail with clear diagnostics
	part, err = store.UploadPart(ctx, key, uploadID, num, data)
}

Prevention

When it happens

Trigger: Calling UploadPart against a UFile endpoint whose successful (200) response omits the Etag header — e.g. a proxy/gateway stripping headers, or a non-standard endpoint returning 200 with an error body.

Common situations: Corporate proxies or CDNs in front of UFile that strip headers; misconfigured UFile bucket domains; region/endpoint mismatches returning unusual responses.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/c392c45df5c77865. Report an issue: GitHub.