{"record":{"id":"aefb8536d1a39174","repo":"gohugoio/hugo","slug":"s-is-a-method-of-type-s-but-returns-no-output","errorCode":null,"errorMessage":"%s is a method of type %s but returns no output","messagePattern":"(.+?) is a method of type (.+?) but returns no output","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/where.go","lineNumber":345,"sourceCode":"\n\tmt := hreflect.GetMethodByNameForType(objPtr.Type(), elemName)\n\tif mt.Func.IsValid() {\n\t\t// Receiver is the first argument.\n\t\targs := []reflect.Value{objPtr}\n\t\tnum := mt.Type.NumIn()\n\t\tmaxNumIn := 1\n\t\tif num > 1 && hreflect.IsContextType(mt.Type.In(1)) {\n\t\t\targs = append(args, ctx)\n\t\t\tmaxNumIn = 2\n\t\t}\n\n\t\tswitch {\n\t\tcase mt.PkgPath != \"\":\n\t\t\treturn zero, fmt.Errorf(\"%s is an unexported method of type %s\", elemName, typ)\n\t\tcase mt.Type.NumIn() > maxNumIn:\n\t\t\treturn zero, fmt.Errorf(\"%s is a method of type %s but requires more than %d parameter\", elemName, typ, maxNumIn)\n\t\tcase mt.Type.NumOut() == 0:\n\t\t\treturn zero, fmt.Errorf(\"%s is a method of type %s but returns no output\", elemName, typ)\n\t\tcase mt.Type.NumOut() > 2:\n\t\t\treturn zero, fmt.Errorf(\"%s is a method of type %s but returns more than 2 outputs\", elemName, typ)\n\t\tcase mt.Type.NumOut() == 1 && mt.Type.Out(0).Implements(errorType):\n\t\t\treturn zero, fmt.Errorf(\"%s is a method of type %s but only returns an error type\", elemName, typ)\n\t\tcase mt.Type.NumOut() == 2 && !mt.Type.Out(1).Implements(errorType):\n\t\t\treturn zero, fmt.Errorf(\"%s is a method of type %s returning two values but the second value is not an error type\", elemName, typ)\n\t\t}\n\t\tres := mt.Func.Call(args)\n\t\tif len(res) == 2 && !res[1].IsNil() {\n\t\t\treturn zero, fmt.Errorf(\"error at calling a method %s of type %s: %s\", elemName, typ, res[1].Interface().(error))\n\t\t}\n\t\treturn res[0], nil\n\t}\n\n\t// elemName isn't a method so next start to check whether it is\n\t// a struct field or a map value. In both cases, it mustn't be\n\t// a nil value\n\tif isNil {","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/where.go#L327-L363","documentation":"`evaluateSubElem` (where.go:344-345) requires a method used as a `where` key to produce a value it can compare against the match argument. If `mt.Type.NumOut() == 0` the method returns nothing, so there is no value to filter on, and Hugo rejects it.","triggerScenarios":"`{{ where $items \"Reset\" \"==\" true }}` against a method `func (i *Item) Reset()` that performs a side effect with no return value.","commonSituations":"Treating a command/mutator method as a query; copy-pasting a method name that happens to be a void action; migrating from a field to a setter method.","solutions":["Filter on a real value: a field or a method that returns the post-reset state.","Expose an exported field carrying the boolean/value you actually want to match.","If you need the side effect, perform it in a `range` before filtering, not as a where key."],"exampleFix":"// before\n{{ where $items \"Reset\" \"==\" true }}  {{/* Reset() returns nothing */}}\n// after\n{{ where $items \"NeedsReset\" \"==\" true }}  {{/* NeedsReset() bool */}}","handlingStrategy":"validation","validationCode":"// Go-side: only allow methods that return at least one value\nmt, ok := reflect.TypeOf(item).MethodByName(name)\nok = ok && mt.Type.NumOut() >= 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reserve `where` keys for value-returning query methods, not mutators.","Name command-style methods (Reset, Save, Load) distinctly from query methods.","Document which methods are template-safe."],"tags":["hugo","go-templates","where","reflection","method-signature"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}