{"id":"cb316195dc04bdae","repo":"gohugoio/hugo","slug":"errkeyisemptystring","errorCode":"errKeyIsEmptyString","errorMessage":"one of the keys is an empty string","messagePattern":"one of the keys is an empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/querify.go","lineNumber":26,"sourceCode":"// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage collections\n\nimport (\n\t\"errors\"\n\t\"net/url\"\n\n\t\"github.com/gohugoio/hugo/common/hmaps\"\n\t\"github.com/spf13/cast\"\n)\n\nvar (\n\terrWrongArgStructure = errors.New(\"expected a map, a slice with an even number of elements, or an even number of scalar values, and each key must be a string\")\n\terrKeyIsEmptyString  = errors.New(\"one of the keys is an empty string\")\n)\n\n// Querify returns a URL query string composed of the given key-value pairs,\n// encoded and sorted by key.\nfunc (ns *Namespace) Querify(params ...any) (string, error) {\n\tif len(params) == 0 {\n\t\treturn \"\", nil\n\t}\n\n\tif len(params) == 1 {\n\t\tswitch v := params[0].(type) {\n\t\tcase map[string]any: // created with collections.Dictionary\n\t\t\treturn mapToQueryString(v)\n\t\tcase hmaps.Params: // project configuration or page parameters\n\t\t\treturn mapToQueryString(v)\n\t\tcase []string:\n\t\t\treturn stringSliceToQueryString(v)\n\t\tcase []any:","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/querify.go#L8-L44","documentation":"While encoding key/value pairs into a query string, `Querify` rejects any key that is the empty string (tpl/collections/querify.go:76-78, 101-103). An empty key would produce a malformed query fragment like `=value`, so Hugo fails fast instead of emitting a broken URL.","triggerScenarios":"`{{ querify \"\" \"value\" }}`; a map built with `dict` where a key variable evaluated to \"\"; an even-length slice whose key positions (index 0, 2, 4…) contain empty strings.","commonSituations":"Keys sourced from front matter or data files where a field is unset and defaults to \"\"; building query pairs in a loop where the key expression (`.name`, `.key`) is empty for some items; whitespace-only-vs-empty confusion after string manipulation like `trim`.","solutions":["Find which key is empty — log the input with `{{ warnf \"%v\" $pairs }}` before calling querify.","Filter out entries with empty keys before building the query: `{{ if $k }}{{ $pairs = $pairs | append $k $v }}{{ end }}`.","Fix the upstream data (front matter, data file) so every entry has a non-empty key, or provide a `default` value."],"exampleFix":"<!-- before: .key may be empty for some items -->\n{{ range $items }}{{ $q = $q | append .key .value }}{{ end }}\n<!-- after -->\n{{ range $items }}{{ with .key }}{{ $q = $q | append . $.value }}{{ end }}{{ end }}\n{{ querify $q }}","handlingStrategy":"validation","validationCode":"{{ range $k, $v := $params }}\n  {{ if eq $k \"\" }}{{ errorf \"querify: empty key in params map\" }}{{ end }}\n{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter out empty-string keys before calling querify, especially for maps built from user content or front matter","Watch for keys produced by splitting strings — a trailing delimiter yields an empty key","Fail fast with errorf rather than silently dropping the pair"],"tags":["hugo","templates","collections","querify","validation"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}