AlistGo/alist · warning

streamtape move to root is not supported by API

Error message

streamtape move to root is not supported by API

What it means

The Streamtape API has no operation to move a file to the account root — moves require a destination folder ID, and the root is identified by an empty or "0" folder ID which the driver rejects before calling the API. This is a deliberate client-side guard, not an API response.

Source

Thrown at drivers/streamtape/driver.go:266

		Name:     dirName,
		IsFolder: true,
	}, nil
}

func (d *Streamtape) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
	if srcObj.IsDir() {
		return nil, errs.NotImplement
	}
	fileID := fileIDFromObjID(srcObj.GetID())
	if fileID == "" {
		return nil, errors.New("empty file id")
	}
	folderID := d.RootFolderID
	if dstDir.GetID() != "" {
		folderID = folderIDFromObjID(dstDir.GetID())
	}
	if folderID == "" || folderID == "0" {
		return nil, fmt.Errorf("streamtape move to root is not supported by API")
	}

	if err := d.callAPI(ctx, "/file/move", map[string]string{
		"file":   fileID,
		"folder": folderID,
	}, nil); err != nil {
		return nil, err
	}

	return &model.Object{
		ID:       srcObj.GetID(),
		Name:     srcObj.GetName(),
		Size:     srcObj.GetSize(),
		Modified: srcObj.ModTime(),
		IsFolder: false,
	}, nil
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Move the file into an existing subfolder instead of the root
  2. Create a folder first (e.g. 'Moved') if you need an intermediate destination
  3. If root placement is required, download and re-upload the file at the root instead of moving
  4. Adjust scripts to never target the root object as a move destination

Example fix

// before
err := fs.Move(ctx, srcObj, rootObj)
// after
dst, _ := fs.MakeDir(ctx, parentObj, "Moved")
err := fs.Move(ctx, srcObj, dst)
Defensive patterns

Strategy: validation

Validate before calling

// before moving, ensure the destination is a real (non-root) folder
func isMovableDestination(dst model.Obj) bool {
    id := dst.GetID()
    return id != "" && id != "0"
}

Type guard

func isStreamtapeRoot(dst model.Obj) bool {
    id := dst.GetID()
    return id == "" || id == "0"
}

Try / catch

if err != nil && strings.Contains(err.Error(), "move to root is not supported") {
    // choose/create a subfolder as destination instead
    dst = ensureSubfolder(ctx, srcParent, "Moved")
}

Prevention

When it happens

Trigger: Calling Move with dstDir whose ID is empty or "0" — i.e. moving a file to the root of the Streamtape storage in the AList UI or via API.

Common situations: User drags a file to the storage root expecting a trash/root folder; scripts that resolve a failed folder lookup to the root object.

Related errors


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