AlistGo/alist · error

upload failed: http %d

Error message

upload failed: http %d

What it means

The POST to the upload server completed but returned an HTTP status other than 200. The response body is not included in the message, so the provider's explanation (auth failure, quota, size limit) is lost. Common codes: 401/403 (bad key), 413 (file too large), 5xx (server-side failure).

Source

Thrown at drivers/darkibox/driver.go:261

	// Step 2: Upload the file to the upload server
	reader := driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
		Reader:         file,
		UpdateProgress: up,
	})

	res, err := base.RestyClient.R().
		SetContext(ctx).
		SetMultipartField("file", file.GetName(), "", reader).
		SetMultipartFormData(map[string]string{
			"key":    d.APIKey,
			"fld_id": fldIDStr(folderID),
		}).
		Post(server.URL)
	if err != nil {
		return nil, fmt.Errorf("upload failed: %w", err)
	}
	if res.StatusCode() != http.StatusOK {
		return nil, fmt.Errorf("upload failed: http %d", res.StatusCode())
	}

	// Try to parse upload response to get the file code
	var uploadResp uploadResult
	if err := base.RestyClient.JSONUnmarshal(res.Body(), &uploadResp); err == nil && len(uploadResp.Files) > 0 {
		uf := uploadResp.Files[0]
		return &model.Object{
			ID:       encodeFileID(uf.FileCode),
			Name:     file.GetName(),
			Size:     file.GetSize(),
			IsFolder: false,
		}, nil
	}

	return &model.Object{
		Name:     file.GetName(),
		Size:     file.GetSize(),
		IsFolder: false,

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Map the status: 401/403 → refresh API key; 413 → split or compress the file / upgrade plan; 5xx → retry later
  2. Include res.Body() in the error (see exampleFix) so the provider's message is visible next time
  3. Verify fld_id still exists by listing the destination folder

Example fix

// before
if res.StatusCode() != http.StatusOK {
	return nil, fmt.Errorf("upload failed: http %d", res.StatusCode())
}
// after
if res.StatusCode() != http.StatusOK {
	return nil, fmt.Errorf("upload failed: http %d: %s", res.StatusCode(), strings.TrimSpace(string(res.Body())))
}
Defensive patterns

Strategy: try-catch

Validate before calling

if file.GetSize() > d.maxFileSize() { // query provider limit
	return errors.New("file exceeds provider size limit")
}

Try / catch

var httpErr matcher // extract code from "upload failed: http %d"
if m := regexp.MustCompile(`upload failed: http (\d+)`).FindStringSubmatch(err.Error()); m != nil {
	switch m[1] {
	case "401", "403": reconfigureKey()
	case "413": splitOrCompress()
	case "502", "503": retryLater()
	}
}

Prevention

When it happens

Trigger: Upload server rejects the multipart request: expired API key sent in the 'key' form field, file exceeds the account's size cap (413), invalid fld_id (404/400), or upload server overloaded (502/503).

Common situations: Free-tier accounts hitting max file size; key revoked between /upload/server and the POST; folder ID from a stale listing deleted server-side.

Related errors


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