{"record":{"id":"09132c18117506e2","repo":"gohugoio/hugo","slug":"called-apply-using-xt-as-type-targ","errorCode":null,"errorMessage":"called apply using {xt} as type {targ}","messagePattern":"called apply using (.+?) as type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/apply.go","lineNumber":102,"sourceCode":"\tif fn.Type().IsVariadic() {\n\t\tnum--\n\t}\n\n\t// TODO(bep) see #1098 - also see template_tests.go\n\t/*if len(args) < num {\n\t\treturn reflect.ValueOf(nil), errors.New(\"Too few arguments\")\n\t} else if len(args) > num {\n\t\treturn reflect.ValueOf(nil), errors.New(\"Too many arguments\")\n\t}*/\n\n\tfor i := range num {\n\t\t// Go's built-in template funcs (e.g. len) use reflect.Value as argument type.\n\t\tif fn.Type().In(i) == typeOfReflectValue && n[i].Type() != typeOfReflectValue {\n\t\t\tn[i] = reflect.ValueOf(n[i])\n\t\t}\n\n\t\tif xt, targ := n[i].Type(), fn.Type().In(i); !xt.AssignableTo(targ) {\n\t\t\treturn reflect.ValueOf(nil), errors.New(\"called apply using \" + xt.String() + \" as type \" + targ.String())\n\t\t}\n\t}\n\n\tres := fn.Call(n)\n\n\tif len(res) == 1 || res[1].IsNil() {\n\t\treturn res[0], nil\n\t}\n\treturn reflect.ValueOf(nil), res[1].Interface().(error)\n}\n\nfunc (ns *Namespace) lookupFunc(ctx context.Context, fname string) (reflect.Value, bool) {\n\tnamespace, methodName, ok := strings.Cut(fname, \".\")\n\tif !ok {\n\t\treturn ns.deps.GetTemplateStore().GetFunc(fname)\n\t}\n\n\t// Namespace","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/apply.go#L84-L120","documentation":"In applyFnToThis (apply.go:101-103) each argument's reflect type is tested with AssignableTo against the target function's parameter type. If an arg (including the \".\" current item) is not assignable, it surfaces both types. This is the type-mismatch gate for reflective invocation.","triggerScenarios":"Applying a string-only function (e.g. upper) to a slice of ints; passing an int arg where the func expects a string; the current element type disagrees with the func's first parameter.","commonSituations":"Applying absURL/upper (string funcs) to a numeric slice; passing a Page where a string is expected; element type changed after a refactor.","solutions":["Match the function's parameter type to the slice element type","Convert elements first (e.g. apply \"string\") before the target function","Use a partial that accepts the actual element type"],"exampleFix":"// before\n{{ apply . \"absURL\" }}  {{/* . is []int */}}\n// after\n{{ apply (apply . \"string\") \"absURL\" }}","handlingStrategy":"type-guard","validationCode":"{{/* convert numeric elements to string before a string function */}}\n{{ $strs := apply . \"string\" }}\n{{ apply $strs \"upper\" }}","typeGuard":"{{/* Go-side guard for programmatic callers */}}\nfunc isStringSlice(v any) bool {\n  t := reflect.TypeOf(v)\n  return (t.Kind() == reflect.Slice || t.Kind() == reflect.Array) && t.Elem().Kind() == reflect.String\n}","tryCatchPattern":null,"preventionTips":["Match the function's parameter type to the slice element type","Pre-convert with apply \"string\" when targeting string funcs","Keep element types stable; review after refactors that change element types"],"tags":["hugo","go-template","collections","type-mismatch","reflect"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}