{"record":{"id":"6589e7d05e97a508","repo":"AlistGo/alist","slug":"streamtape-move-to-root-is-not-supported-by-api","errorCode":null,"errorMessage":"streamtape move to root is not supported by API","messagePattern":"streamtape move to root is not supported by API","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"drivers/streamtape/driver.go","lineNumber":266,"sourceCode":"\t\tName:     dirName,\n\t\tIsFolder: true,\n\t}, nil\n}\n\nfunc (d *Streamtape) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {\n\tif srcObj.IsDir() {\n\t\treturn nil, errs.NotImplement\n\t}\n\tfileID := fileIDFromObjID(srcObj.GetID())\n\tif fileID == \"\" {\n\t\treturn nil, errors.New(\"empty file id\")\n\t}\n\tfolderID := d.RootFolderID\n\tif dstDir.GetID() != \"\" {\n\t\tfolderID = folderIDFromObjID(dstDir.GetID())\n\t}\n\tif folderID == \"\" || folderID == \"0\" {\n\t\treturn nil, fmt.Errorf(\"streamtape move to root is not supported by API\")\n\t}\n\n\tif err := d.callAPI(ctx, \"/file/move\", map[string]string{\n\t\t\"file\":   fileID,\n\t\t\"folder\": folderID,\n\t}, nil); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &model.Object{\n\t\tID:       srcObj.GetID(),\n\t\tName:     srcObj.GetName(),\n\t\tSize:     srcObj.GetSize(),\n\t\tModified: srcObj.ModTime(),\n\t\tIsFolder: false,\n\t}, nil\n}\n","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/streamtape/driver.go#L248-L284","documentation":"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.","triggerScenarios":"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.","commonSituations":"User drags a file to the storage root expecting a trash/root folder; scripts that resolve a failed folder lookup to the root object.","solutions":["Move the file into an existing subfolder instead of the root","Create a folder first (e.g. 'Moved') if you need an intermediate destination","If root placement is required, download and re-upload the file at the root instead of moving","Adjust scripts to never target the root object as a move destination"],"exampleFix":"// before\nerr := fs.Move(ctx, srcObj, rootObj)\n// after\ndst, _ := fs.MakeDir(ctx, parentObj, \"Moved\")\nerr := fs.Move(ctx, srcObj, dst)","handlingStrategy":"validation","validationCode":"// before moving, ensure the destination is a real (non-root) folder\nfunc isMovableDestination(dst model.Obj) bool {\n    id := dst.GetID()\n    return id != \"\" && id != \"0\"\n}","typeGuard":"func isStreamtapeRoot(dst model.Obj) bool {\n    id := dst.GetID()\n    return id == \"\" || id == \"0\"\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"move to root is not supported\") {\n    // choose/create a subfolder as destination instead\n    dst = ensureSubfolder(ctx, srcParent, \"Moved\")\n}","preventionTips":["Never target the root object as a Streamtape move destination","Create an intermediate folder when a root-level outcome is needed","Scripts should validate destination IDs before calling Move"],"tags":["streamtape","move","api-limitation","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}