gohugoio/hugo · error
errWrongArgStructure
errWrongArgStructure
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
`collections.Querify` builds a URL query string and accepts exactly three input shapes: a single map, a single slice with an even number of elements, or an even number of scalar key/value arguments (tpl/collections/querify.go:31-64). `errWrongArgStructure` is returned when the single argument is some other type, or when the element/argument count is odd — because query strings are strictly key/value pairs.
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 8a468df065)
Solutions
- Count your arguments: every key needs a value — `querify "a" 1 "b" 2`.
- When building the input dynamically, use a dict instead of a slice so pairing is enforced: `querify (dict "a" 1 "b" 2)`.
- If passing one argument, make sure it's a map or an even-length slice, not a pre-built string.
- Debug with `{{ warnf "%v" $args }}` to inspect the actual shape at build time.
Example fix
<!-- before: odd number of args -->
{{ querify "page" 2 "sort" }}
<!-- after -->
{{ querify "page" 2 "sort" "date" }} Defensive patterns
Strategy: validation
Validate before calling
{{/* querify accepts: a map, a slice with even length, or even scalar args with string keys */}}
{{ $kv := dict "page" 1 "sort" "date" }}
{{ $q := querify $kv }}
{{/* if using a slice: */}}
{{ if ne (mod (len $pairs) 2) 0 }}{{ errorf "querify: odd number of elements" }}{{ end }} Type guard
{{ $ok := true }}
{{ range $i, $v := $pairs }}
{{ if and (eq (mod $i 2) 0) (not (reflect.IsString $v)) }}{{ $ok = false }}{{ end }}
{{ end }} Prevention
- Prefer passing a dict to querify — it sidesteps both the even-count and key-type rules
- When passing pairs, verify even length and that every even-index element is a string
- Beware numeric front-matter values used as keys — convert with `string` first
When it happens
Trigger: `{{ querify "a" 1 "b" }}` (odd argument count); `{{ querify (slice "a" "1" "b") }}` (odd-length slice); `{{ querify .Page }}` or any single argument that isn't a map or slice, such as a plain string or number.
Common situations: Building pagination or filter links and forgetting a value for the last key; passing a raw query string ("a=1&b=2") expecting parsing; passing `.Params` values of unexpected shape; templates that append conditionally to a slice and end up with an odd length.
Related errors
- errKeyIsEmptyString
- symdiff: failed to convert value: %w
- arguments to symdiff must be slices or arrays
- complement needs at least two arguments
- arguments to complement must be slices or arrays
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/32526316911446eb.json.
Report an issue: GitHub ↗.