{"record":{"id":"193ccf50a01ecf02","repo":"AlistGo/alist","slug":"missing-file-id-193ccf","errorCode":null,"errorMessage":"missing file id","messagePattern":"missing file id","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/yunpan360/util.go","lineNumber":344,"sourceCode":"\t\tmerged[key] = value\n\t}\n\treturn merged\n}\n\nfunc (d *Yunpan360) cookieDownloadURL(ctx context.Context, file model.Obj) (*CookieDownloadResp, error) {\n\tresp, err := d.cookieDownloadURLOnce(ctx, file, false)\n\tif err == nil {\n\t\treturn resp, nil\n\t}\n\n\td.invalidateCookieDownloadSession()\n\treturn d.cookieDownloadURLOnce(ctx, file, true)\n}\n\nfunc (d *Yunpan360) cookieDownloadURLOnce(ctx context.Context, file model.Obj, refresh bool) (*CookieDownloadResp, error) {\n\tnid := strings.TrimSpace(file.GetID())\n\tif nid == \"\" {\n\t\treturn nil, errors.New(\"missing file id\")\n\t}\n\n\tfname := normalizeRemotePath(file.GetPath())\n\tif fname == \"\" {\n\t\treturn nil, errors.New(\"missing file path\")\n\t}\n\n\townerQID, token, err := d.resolveCookieDownloadParams(ctx, file, refresh)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar resp CookieDownloadResp\n\terr = d.cookieRequestForm(ctx, downloadPath, map[string]string{\n\t\t\"nid\":       nid,\n\t\t\"fname\":     fname,\n\t\t\"owner_qid\": ownerQID,\n\t\t\"token\":     token,","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/yunpan360/util.go#L326-L362","documentation":"A guard in cookieDownloadURLOnce: building a download URL in cookie mode requires the file's nid (360's numeric id). If model.Obj.GetID() is empty or whitespace, the request cannot be formed and this error returns immediately (drivers/yunpan360/util.go:344).","triggerScenarios":"Calling the driver's link/download path with an object that has no ID set — e.g. a synthetic model.Obj constructed by caller code, an object built only from a path (root dir placeholder), or an object whose ID was lost during conversion/mapping before download.","commonSituations":"Custom code creates model.Obj implementations (e.g. model.Object with only Path set) and passes them to a download API; a directory object (dirs often have no usable nid for download) is passed to a file-download call; upcasting/copy bugs strip the ID field.","solutions":["Ensure the object passed to download comes from a real driver List() result, not a hand-built struct","Set the ID field from the listing's nid before requesting a download link","Verify callers are not passing directories to file-download APIs","If mapping objects between layers, copy the ID field explicitly"],"exampleFix":"// before\nfile := &model.Object{Path: \"/docs/a.txt\"} // no ID\nlink, err := d.Link(ctx, file, model.LinkArgs{})\n\n// after\nfile := &model.Object{Path: \"/docs/a.txt\", ID: \"123456789\"}\nlink, err := d.Link(ctx, file, model.LinkArgs{})","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(file.GetID()) == \"\" { return errors.New(\"refusing download: object has no ID\") }","typeGuard":"func hasFileID(obj model.Obj) bool { return strings.TrimSpace(obj.GetID()) != \"\" }","tryCatchPattern":"if !hasFileID(file) {\n    file = refreshFromList(ctx, file) // re-list parent, match by path\n}\nresp, err := d.cookieDownloadURL(ctx, file)\nif err != nil { return nil, err }","preventionTips":["Never construct download targets manually; source them from List()","Add a capability check in caller code: skip download for objects lacking IDs","Directories: exclude from download calls explicitly"],"tags":["yunpan360","validation","download","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}