{"record":{"id":"c045431f2eee5943","repo":"AlistGo/alist","slug":"failed-to-render-download-params-w","errorCode":null,"errorMessage":"failed to render download_params: %w","messagePattern":"failed to render download_params: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/url_tree/driver.go","lineNumber":118,"sourceCode":"\t\treturn &model.Link{\n\t\t\tURL: downURL,\n\t\t}, nil\n\t}\n\treturn nil, errs.NotFile\n}\n\n// buildDownloadURL renders the configured download_params template with the\n// node's magic variables and appends the result as query parameters to the URL.\nfunc (d *Urls) buildDownloadURL(node *Node, path string) (string, error) {\n\tvar sb strings.Builder\n\terr := d.downloadParamsTmpl.Execute(&sb, map[string]interface{}{\n\t\t\"Name\":     node.Name,\n\t\t\"Path\":     path,\n\t\t\"Size\":     node.Size,\n\t\t\"Modified\": node.Modified,\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to render download_params: %w\", err)\n\t}\n\trendered := strings.TrimSpace(sb.String())\n\trendered = strings.TrimPrefix(rendered, \"?\")\n\tif rendered == \"\" {\n\t\treturn node.Url, nil\n\t}\n\t// Parse the rendered string so that magic-variable values (e.g. file names\n\t// with non-ASCII characters) are properly URL-encoded by Encode().\n\tquery, err := url.ParseQuery(rendered)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid download_params %q: %w\", rendered, err)\n\t}\n\treturn utils.InjectQuery(node.Url, query)\n}\n\nfunc (d *Urls) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {\n\tif !d.Writable {\n\t\treturn nil, errs.PermissionDenied","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/url_tree/driver.go#L100-L136","documentation":"While building a download link, the url_tree driver executes the previously parsed download_params template with the node's magic variables (Name, Path, Size, Modified). Execution fails if the template references a field that is not provided or a function errors at runtime; the error is wrapped and the Link call fails for that file.","triggerScenarios":"A template that parsed fine but references {{.Missing}} (nil field) or uses functions that error during Execute when called from buildDownloadURL for a specific node/path.","commonSituations":"Typo in a field name like {{.Filename}} instead of {{.Name}}, or expecting per-node fields that the driver does not inject. Storage initializes fine but every download fails.","solutions":["Restrict template fields to exactly Name, Path, Size, Modified; fix typos such as {{.Filename}} -> {{.Name}}.","Test the template with dummy values mirroring those four keys to confirm it renders.","Simplify: remove custom template functions; text/template built-ins only are supported."],"exampleFix":"// before\ndownload_params = \"fname={{.Filename}}\"\n\n// after\ndownload_params = \"fname={{.Name}}\"","handlingStrategy":"validation","validationCode":"var allowedFields = map[string]bool{\"Name\": true, \"Path\": true, \"Size\": true, \"Modified\": true}\n// after parsing, walk template.Tree and reject .Field lookups not in allowedFields\nfunc checkFields(t *template.Template) error {\n    _, err := t.Execute(nil, map[string]any{\"Name\": \"x\", \"Path\": \"/x\", \"Size\": int64(1), \"Modified\": int64(0)})\n    return err // nil map input still executes field lookups; use dummy values\n}","typeGuard":null,"tryCatchPattern":"url, err := d.buildDownloadURL(node, path)\nif err != nil && strings.Contains(err.Error(), \"failed to render\") {\n    // log node identity and template; fall back to raw node.Url if acceptable\n}","preventionTips":["Test template execution with dummy values for all four variables before deploying","Never reference fields outside Name/Path/Size/Modified","Log the failing node to identify which file's data broke rendering"],"tags":["url-tree","template","runtime","config"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}