AlistGo/alist · error

file is nil

Error message

file is nil

What it means

GuangYaPan Put guards against a nil model.FileStreamer before using it. A nil stream means the upload request itself is malformed — no file payload reached the driver — so it aborts before requesting an upload token.

Source

Thrown at drivers/guangyapan/driver.go:382

	}, &out); err != nil {
		return err
	}
	if !strings.EqualFold(strings.TrimSpace(out.Msg), "success") {
		return fmt.Errorf("copy failed: %s", strings.TrimSpace(out.Msg))
	}
	taskID := strings.TrimSpace(out.Data.TaskID)
	if taskID == "" {
		return nil
	}
	return d.waitTaskDone(ctx, taskID)
}

func (d *GuangYaPan) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
	if err := d.ensureAccessToken(ctx); err != nil {
		return err
	}
	if file == nil {
		return errors.New("file is nil")
	}
	if file.GetSize() < 0 {
		return errors.New("invalid file size")
	}
	name := strings.TrimSpace(file.GetName())
	if name == "" {
		return errors.New("file name is empty")
	}

	parentID := dstDir.GetID()

	token, code, err := d.getUploadToken(ctx, parentID, name, file.GetSize())
	if err != nil {
		return err
	}
	taskID := strings.TrimSpace(token.TaskID)
	if code == 156 {
		if taskID == "" {

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check the caller: ensure the streamer is built and non-nil before Put
  2. If a stream constructor returns (nil, err), handle err instead of continuing
  3. Reproduce with a normal UI upload; if that works, the bug is in the custom caller

Example fix

// before
stream, err := NewStreamer(r)
_ = err // ignored; stream may be nil
d.Put(ctx, dir, stream, up)
// after
stream, err := NewStreamer(r)
if err != nil { return err }
return d.Put(ctx, dir, stream, up)
Defensive patterns

Strategy: validation

Validate before calling

if file == nil {
	return errors.New("upload aborted: no file stream provided")
}
return d.Put(ctx, dstDir, file, up)

Type guard

func hasStream(f model.FileStreamer) bool { return f != nil }

Try / catch

stream, err := buildStreamer(req)
if err != nil { return err }
if stream == nil { return errors.New("internal: stream construction returned nil") }
return d.Put(ctx, dstDir, stream, up)

Prevention

When it happens

Trigger: Programmatically invoking Put with a nil file argument; upstream proxying code that failed to construct the streamer (e.g. a multipart parse failure swallowed earlier) and passed nil through.

Common situations: Custom integrations calling the driver directly; bugs in middleware that forwards uploads; nil returned by a stream constructor on error and not checked.

Related errors


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