gohugoio/hugo · error
expected a map, a slice with an even number of elements, or
Error message
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
What it means
The `querify` function builds a URL query string from key-value pairs, encoded and sorted by key. This error covers three shapes of bad input: a single argument that is not a map, a `hmaps.Params`, a `[]string`, or a `[]any`; an odd number of scalar variadic arguments (key without value); or a `[]string`/`[]any` slice with an odd element count.
Source
Thrown at tpl/collections/querify.go:25
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package collections
import (
"errors"
"net/url"
"github.com/gohugoio/hugo/common/hmaps"
"github.com/spf13/cast"
)
var (
errWrongArgStructure = 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")
errKeyIsEmptyString = errors.New("one of the keys is an empty string")
)
// Querify returns a URL query string composed of the given key-value pairs,
// encoded and sorted by key.
func (ns *Namespace) Querify(params ...any) (string, error) {
if len(params) == 0 {
return "", nil
}
if len(params) == 1 {
switch v := params[0].(type) {
case map[string]any: // created with collections.Dictionary
return mapToQueryString(v)
case hmaps.Params: // project configuration or page parameters
return mapToQueryString(v)
case []string:
return stringSliceToQueryString(v)View on GitHub (pinned to 52c9bd7908)
Solutions
- Ensure scalar arguments come in key-value pairs: `{{ querify "foo" "bar" "baz" "qux" }}`.
- Pass a `dict` or `hmaps.Params` for a single-argument form: `{{ querify (dict "foo" "bar") }}`.
- If using a slice, guarantee an even number of string-castable elements.
Example fix
// before
{{ querify "q" }}
// after
{{ querify "q" "hugo" }}
// or
{{ querify (dict "q" "hugo" "page" "1") }} Defensive patterns
Strategy: validation
Validate before calling
// Validate key-value pairing before querify
{{ $pairs := slice "k1" "v1" "k2" "v2" }}
{{ if eq (mod (len $pairs) 2) 0 }}
{{ querify $pairs }}
{{ end }} Type guard
func isValidQuerifyInput(params []any) bool {
if len(params) == 0 { return true }
if len(params) == 1 {
switch params[0].(type) {
case map[string]any, hmaps.Params, []string, []any: return true
default: return false
}
}
return len(params)%2 == 0
} Prevention
- Always pass an even number of scalar arguments (key, value, key, value).
- Prefer the single-dict form `querify (dict ...)` for clarity.
- Ensure slice elements can be cast to strings.
When it happens
Trigger: Passing an odd number of scalar args (`{{ querify "foo" }}`), passing a single unsupported type (`{{ querify 42 }}`), or passing a slice with an odd length (`{{ querify (slice "a" "1" "b") }}`). The checks fire at querify.go:51 (unsupported single type), querify.go:56 (odd scalar count), and querify.go:96 (odd slice length).
Common situations: A developer forgets the value half of a key-value pair, or passes a struct/number where a map or string pairs are expected. Also seen when front matter values are conditionally included, leaving a dangling key after a `del` or absent value.
Related errors
- nil is not a valid key to group by
- argument must be a slice
- size of result exceeds limit
- invalid number of arguments to Seq
- invalid arguments to Seq
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/3b5dcc3390322731.
Report an issue: GitHub.