{"id":"8c6fc630f4a5613a","repo":"gohugoio/hugo","slug":"failed-to-decode-options-for-resource-s-w","errorCode":null,"errorMessage":"failed to decode options for resource %s: %w","messagePattern":"failed to decode options for resource (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/create/remote.go","lineNumber":232,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid timeout for resource %s: %w\", uri, err)\n\t\t}\n\t\tperRequestTimeout = d\n\t\tdelete(optionsm, k)\n\t}\n\n\tuserKey, optionsKey := remoteResourceKeys(uri, optionsm)\n\n\t// A common pattern is to use the key in the options map as\n\t// a way to control cache eviction,\n\t// so make sure we use any user provided key as the file cache key,\n\t// but the auto generated and more stable key for everything else.\n\tfilecacheKey := userKey\n\n\treturn c.rs.ResourceCache.CacheResourceRemote.GetOrCreate(optionsKey, func(key string) (resource.Resource, error) {\n\t\toptions, err := decodeRemoteOptions(optionsm)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to decode options for resource %s: %w\", uri, err)\n\t\t}\n\n\t\tif err := c.validateFromRemoteArgs(uri, options); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tgetRes := func() (*http.Response, context.CancelFunc, error) {\n\t\t\tctx := context.Background()\n\t\t\tvar cancel context.CancelFunc\n\t\t\tif perRequestTimeout > 0 {\n\t\t\t\tctx, cancel = context.WithTimeout(ctx, perRequestTimeout)\n\t\t\t}\n\t\t\tctx = c.resourceIDDispatcher.Set(ctx, filecacheKey)\n\n\t\t\treq, err := options.NewRequest(uri)\n\t\t\tif err != nil {\n\t\t\t\tif cancel != nil {\n\t\t\t\t\tcancel()","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/resources/resource_factories/create/remote.go#L214-L250","documentation":"Inside the cached fetch closure, `resources.GetRemote`'s options map is decoded into a typed struct (headers, method, body, key, responseHeaders, etc.) via `decodeRemoteOptions`. If the map contains keys of the wrong shape or values that can't be mapped onto the expected fields, decoding fails and this wrapped error is returned before any HTTP request is made.","triggerScenarios":"Passing an options dict with malformed values, e.g. `headers` as a plain string instead of a map, `body` as an unsupported type, `responseHeaders` not a string slice, or an unknown-typed value where a string/map is expected in the `resources.GetRemote $url $opts` call.","commonSituations":"Copying options examples across Hugo versions where the schema changed, building the dict from front matter/data files where YAML produced a different type than expected (map vs list of maps for headers), or misspelling a nested structure so a scalar lands where a map is required.","solutions":["Check the options against the current `resources.GetRemote` docs; headers must be a map, e.g. `dict \"headers\" (dict \"Authorization\" $token)`.","Inspect the wrapped cause in the error message — it names the offending field — and fix that key's type.","Print the dict with `warnf \"%v\"` (redacting secrets) to confirm YAML/TOML produced the structure you expect."],"exampleFix":"{{/* before */}}\n{{ $opts := dict \"headers\" \"Authorization: Bearer x\" }}\n{{/* after */}}\n{{ $opts := dict \"headers\" (dict \"Authorization\" \"Bearer x\") }}","handlingStrategy":"validation","validationCode":"{{/* keep GetRemote options to known keys with correct shapes */}}\n{{ $opts := dict\n  \"method\" \"post\"\n  \"headers\" (dict \"Authorization\" (printf \"Bearer %s\" (getenv \"API_TOKEN\")))\n  \"body\" (jsonify (dict \"q\" \"hugo\"))\n}}\n{{ $r := resources.GetRemote $url $opts }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use only documented option keys: method, headers, body, key, timeout — typos and wrong value types fail decoding","headers must be a map of string to string (or slice of strings), not nested structures","Build options with dict in one place and reuse via a partial instead of hand-writing them per call"],"tags":["hugo","get-remote","options","decoding","templates"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}