{"record":{"id":"be335421ac8bca02","repo":"AlistGo/alist","slug":"missing-source-file-id","errorCode":null,"errorMessage":"missing source file id","messagePattern":"missing source file id","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/wukong/driver.go","lineNumber":216,"sourceCode":"\t\tSetBody(map[string]any{\n\t\t\t\"father_id\": asIDValue(fatherID),\n\t\t\t\"file_name\": dirName,\n\t\t}).\n\t\tSetResult(&resp).\n\t\tPost(\"/netdisk/user_file/create_directory\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif resp.Code != 0 {\n\t\treturn fmt.Errorf(\"wukong create directory failed: code=%d message=%s\", resp.Code, resp.Message)\n\t}\n\treturn nil\n}\n\nfunc (d *Wukong) Move(ctx context.Context, srcObj, dstDir model.Obj) error {\n\tsrcID := srcObj.GetID()\n\tif srcID == \"\" {\n\t\treturn errors.New(\"missing source file id\")\n\t}\n\n\tdstID := dstDir.GetID()\n\tif dstID == \"\" {\n\t\tdstID = d.RootFolderID\n\t}\n\n\tvar resp rawResp\n\t_, err := d.client.R().\n\t\tSetContext(ctx).\n\t\tSetQueryParams(map[string]string{\n\t\t\t\"aid\":             d.Aid,\n\t\t\t\"device_platform\": \"web\",\n\t\t\t\"language\":        d.Language,\n\t\t}).\n\t\tSetBody(map[string]any{\n\t\t\t\"file_id_list\":  []any{asIDValue(srcID)},\n\t\t\t\"new_father_id\": asIDValue(dstID),","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/wukong/driver.go#L198-L234","documentation":"Thrown by Wukong's Move() when the source object's ID is empty. The move API posts a file_id for the object being relocated; an empty ID means the request payload would be meaningless, so the driver bails out before the HTTP call. Note the asymmetry: the destination may legitimately be empty (falls back to d.RootFolderID), but the source may not.","triggerScenarios":"Calling Move() with a srcObj that never came from Wukong List() — e.g. an object built from a raw path, a deserialized object that lost its ID, or an object from a different driver/mount passed by mistake.","commonSituations":"Cross-driver copy/move helpers that pass path-derived objects; object caches that drop IDs; moving an object that was concurrently deleted and re-created (stale reference).","solutions":["List() the source's parent directory and pass the fresh object (with its ID) as srcObj","Check srcObj.GetID() != \"\" before calling Move and fail fast with context about which path lacked an ID","Ensure any object cache or job queue preserves the Wukong file ID field"],"exampleFix":"// before\nerr := d.Move(ctx, srcObj, dstDir)\n\n// after\nif srcObj.GetID() == \"\" {\n    return fmt.Errorf(\"cannot move %q: wukong object has no file id; re-list parent to refresh\", srcObj.GetPath())\n}\nerr := d.Move(ctx, srcObj, dstDir)","handlingStrategy":"validation","validationCode":"if srcObj.GetID() == \"\" {\n    return fmt.Errorf(\"wukong: cannot move %q without file id; re-list source directory\", srcObj.GetPath())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve source objects via List() before Move","Persist the Wukong file ID in job queues for async moves","Remember dstDir may be empty (root fallback) but srcObj may not"],"tags":["wukong","driver","move","object-id","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}