{"record":{"id":"fb9048098e2f92bc","repo":"AlistGo/alist","slug":"offline-url-is-empty","errorCode":null,"errorMessage":"offline url is empty","messagePattern":"offline url is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"drivers/guangyapan/offline.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\tstdpath \"path\"\n\t\"strings\"\n\n\t\"github.com/alist-org/alist/v3/internal/model\"\n)\n\nfunc (d *GuangYaPan) ResolveOfflineResource(ctx context.Context, fileURL string) (*OfflineResolveData, error) {\n\tif err := d.ensureAccessToken(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\tfileURL = strings.TrimSpace(fileURL)\n\tif fileURL == \"\" {\n\t\treturn nil, errors.New(\"offline url is empty\")\n\t}\n\n\tvar resp offlineResolveResp\n\tif err := d.postAPI(ctx, \"/cloudcollection/v1/resolve_res\", map[string]any{\n\t\t\"url\": fileURL,\n\t}, &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif !isSuccessMsg(resp.Msg) {\n\t\treturn nil, fmt.Errorf(\"resolve offline resource failed: %s\", strings.TrimSpace(resp.Msg))\n\t}\n\treturn &resp.Data, nil\n}\n\nfunc (d *GuangYaPan) OfflineDownload(ctx context.Context, fileURL string, parentDir model.Obj, fileName string) (*OfflineTask, error) {\n\tresolved, err := d.ResolveOfflineResource(ctx, fileURL)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/guangyapan/offline.go#L2-L38","documentation":"ResolveOfflineResource trims the incoming fileURL and rejects an empty string before calling POST /cloudcollection/v1/resolve_res. It is a pure input-validation error: the offline-download resolver has nothing to resolve. All later API work (auth, rate limit, resolve call) is skipped.","triggerScenarios":"ResolveOfflineResource called with \"\", \"   \", or a URL consisting only of whitespace. Typically the value came straight from user input in an offline-download task form.","commonSituations":"Frontend submitted an empty URL field; task-creation pipeline passed an unmarshalled JSON field that was absent; automation script iterated over a list with blank entries.","solutions":["Validate the URL client-side before creating the offline task (required field, non-blank)","In calling code, skip/filter empty entries when batch-creating offline tasks","URL-encode the value after trimming to avoid whitespace-only strings slipping through"],"exampleFix":"// before\nresolve, err := d.ResolveOfflineResource(ctx, taskURL)\n// after\nif strings.TrimSpace(taskURL) == \"\" {\n\treturn errors.New(\"offline task url must not be empty\")\n}\nresolve, err := d.ResolveOfflineResource(ctx, taskURL)","handlingStrategy":"validation","validationCode":"url := strings.TrimSpace(fileURL)\nif url == \"\" {\n\treturn nil, errors.New(\"offline download URL is required\")\n}\nif !strings.Contains(url, \"://\") {\n\treturn nil, fmt.Errorf(\"offline download URL looks invalid: %q\", url)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mark the URL field required in the offline-task UI and trim input before submission","Filter blank entries when batch-submitting offline tasks"],"tags":["guangyapan","validation","offline-download","driver"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}