{"record":{"id":"928711feb9799c45","repo":"AlistGo/alist","slug":"missing-file-id","errorCode":null,"errorMessage":"missing file id","messagePattern":"missing file id","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/wukong/driver.go","lineNumber":144,"sourceCode":"\t\t\t\tIsFolder: item.IsDirectory == 1,\n\t\t\t})\n\t\t}\n\n\t\tif !hasMore(resp.Data.HasMore) || len(resp.Data.FileList) == 0 {\n\t\t\tbreak\n\t\t}\n\t\toffset += len(resp.Data.FileList)\n\t}\n\treturn objs, nil\n}\n\nfunc (d *Wukong) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {\n\tif file.IsDir() {\n\t\treturn nil, errs.NotFile\n\t}\n\tfileID := file.GetID()\n\tif fileID == \"\" {\n\t\treturn nil, errors.New(\"missing file id\")\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(fileID)},\n\t\t}).\n\t\tSetResult(&resp).\n\t\tPost(\"/netdisk/user_file/detail\")\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/wukong/driver.go#L126-L162","documentation":"Thrown by Wukong driver's Link() when a download link is requested for a file object whose ID is an empty string. The Wukong (wkbrowser) API identifies files solely by numeric file_id; without it the /open/file/link style request cannot be formed, so the driver refuses early instead of sending a guaranteed-to-fail request. It fires after the IsDir check, so it only occurs for file objects (not directories).","triggerScenarios":"Calling Link() on a model.Obj obtained from somewhere other than a fresh Wukong List() — e.g. an object reconstructed from a path by the framework, a cached/stale object whose ID was lost during serialization, or a manually constructed Obj with only Name/Path set.","commonSituations":"Using AList's path-to-object resolution on a mount where IDs are not persisted; object metadata caches that drop the ID field; calling driver APIs programmatically with hand-built objects; racing a Remove/Rename that invalidated the object.","solutions":["Re-list the parent directory via List() and pass the returned object (which carries a real file ID) to Link()","Verify file.GetID() != \"\" before invoking Link and surface a clearer upstream error if empty","If objects come from your own cache, make sure the ID field round-trips through serialization"],"exampleFix":"// before\nlink, err := wukongDriver.Link(ctx, someFile, args)\n\n// after\nif someFile.GetID() == \"\" {\n    fresh, err := wukongDriver.List(ctx, parentDir, model.ListArgs{})\n    // resolve someFile by name in fresh, then Link the fresh object\n}\nlink, err := wukongDriver.Link(ctx, freshFile, args)","handlingStrategy":"validation","validationCode":"if file.IsDir() { return errs.NotFile }\nif file.GetID() == \"\" {\n    return nil, fmt.Errorf(\"wukong: object %q has no file id; refresh listing before Link\", file.GetPath())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass objects obtained from Wukong List() to Link(), never path-constructed ones","Keep object ID in any cache/serialization layer","On this error, auto-refresh the parent listing once before failing"],"tags":["wukong","driver","download-link","object-id","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}