AlistGo/alist · error · StreamIncomplete

upload/download stream incomplete, possible network issue

Error message

upload/download stream incomplete, possible network issue

What it means

StreamIncomplete signals that a transfer stream ended prematurely — bytes actually read or written did not match the expected size, or a cloud API reported an incomplete upload. It is defined in internal/errs/errors.go and wrapped via errs.NewErr by drivers such as baidu_netdisk and baidu_youth when they verify response bodies or uploaded file sizes.

Source

Thrown at internal/errs/errors.go:20

import (
	"errors"
	"fmt"

	pkgerr "github.com/pkg/errors"
)

var (
	NotImplement = errors.New("not implement")
	NotSupport   = errors.New("not support")
	RelativePath = errors.New("access using relative path is not allowed")

	MoveBetweenTwoStorages = errors.New("can't move files between two storages, try to copy")
	UploadNotSupported     = errors.New("upload not supported")

	MetaNotFound     = errors.New("meta not found")
	StorageNotFound  = errors.New("storage not found")
	StreamIncomplete = errors.New("upload/download stream incomplete, possible network issue")
	StreamPeekFail   = errors.New("StreamPeekFail")

	UnknownArchiveFormat      = errors.New("unknown archive format")
	WrongArchivePassword      = errors.New("wrong archive password")
	DriverExtractNotSupported = errors.New("driver extraction not supported")
)

// NewErr wrap constant error with an extra message
// use errors.Is(err1, StorageNotFound) to check if err belongs to any internal error
func NewErr(err error, format string, a ...any) error {
	return fmt.Errorf("%w; %s", err, fmt.Sprintf(format, a...))
}

func IsNotFoundError(err error) bool {
	return errors.Is(pkgerr.Cause(err), ObjectNotFound) || errors.Is(pkgerr.Cause(err), StorageNotFound)
}

func IsNotSupportError(err error) bool {

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Retry the transfer (typically a transient network condition)
  2. Check network stability, proxy/CDN timeouts, and rate limits on the cloud provider
  3. Verify local disk space for TempDir when large uploads stage through temp files
  4. If persistent for one provider, re-authorize the storage — expired tokens sometimes produce HTML error pages that parse as truncated bodies

Example fix

// before
err := fs.Copy(ctx, src, dst, nil)

// after
err := fs.Copy(ctx, src, dst, nil)
if err != nil && errors.Is(errors.Cause(err), errs.StreamIncomplete) {
    // safe to retry the copy; remove partial destination first
}
Defensive patterns

Strategy: retry

Type guard

func isStreamIncomplete(err error) bool {
    return err != nil && errors.Is(errors.Cause(err), errs.StreamIncomplete)
}

Try / catch

err := fs.Copy(ctx, src, dst, nil)
if isStreamIncomplete(err) {
    backoff.Retry(cleanPartialAndCopy, 3) // remove partial dst, then retry
}

Prevention

When it happens

Trigger: Baidu netdisk driver getting a truncated/invalid response body during upload (drivers/baidu_netdisk/driver.go:454); baidu_youth detecting temp-file size mismatch between bytes written and the stream's declared size (drivers/baidu_youth/driver.go:287); baidu_youth util receiving a short error body (drivers/baidu_youth/util.go:572). In general, dropped connections mid-copy between AList and the remote storage.

Common situations: Unstable network or proxy timeouts on large uploads; remote provider throttling or resetting connections; disk full so the temp file is truncated; copy/move between two storages where the download side stalls. Transient — usually resolves on retry.

Related errors


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