{"record":{"id":"2899f35a55f10b98","repo":"caddyserver/caddy","slug":"maybe-s-invalid-number-of-return-values-d","errorCode":null,"errorMessage":"maybe %s: invalid number of return values: %d","messagePattern":"maybe (.+?): invalid number of return values: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/templates/tplcontext.go","lineNumber":541,"sourceCode":"\t\t\t}\n\t\t\targVals := make([]reflect.Value, len(args))\n\t\t\tfor i, arg := range args {\n\t\t\t\targVals[i] = reflect.ValueOf(arg)\n\t\t\t}\n\t\t\treturnVals := val.Call(argVals)\n\t\t\tswitch len(returnVals) {\n\t\t\tcase 0:\n\t\t\t\treturn \"\", nil\n\t\t\tcase 1:\n\t\t\t\treturn returnVals[0].Interface(), nil\n\t\t\tcase 2:\n\t\t\t\tvar err error\n\t\t\t\tif !returnVals[1].IsNil() {\n\t\t\t\t\terr = returnVals[1].Interface().(error)\n\t\t\t\t}\n\t\t\t\treturn returnVals[0].Interface(), err\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"maybe %s: invalid number of return values: %d\", functionName, len(returnVals))\n\t\t\t}\n\t\t}\n\t}\n\tc.config.logger.Named(\"maybe\").Warn(\"template function could not be found; ignoring invocation\", zap.String(\"name\", functionName))\n\treturn \"\", nil\n}\n\n// WrappedHeader wraps niladic functions so that they\n// can be used in templates. (Template functions must\n// return a value.)\ntype WrappedHeader struct{ http.Header }\n\n// Add adds a header field value, appending val to\n// existing values for that field. It returns an\n// empty string.\nfunc (h WrappedHeader) Add(field, val string) string {\n\th.Header.Add(field, val)\n\treturn \"\"","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/templates/tplcontext.go#L523-L559","documentation":"Returned by the templates module's {{ maybe ... }} function when a custom template-function module (http.handlers.templates.functions namespace) was invoked successfully via reflection but its Go function returns more than two values. maybe accepts 0, 1, or (value, error) return shapes only.","triggerScenarios":"Writing a custom template extension whose function signature returns e.g. (string, error, int) or three values; calling it through {{ maybe myFunc args }} then fails at the return-shape check.","commonSituations":"Plugin authors reusing an existing multi-return helper as a template function, or refactoring a 2-return function into 3 returns without updating the template invocation.","solutions":["Change the custom function to return at most two values: (), (T), or (T, error)","Fold extra return data into the returned struct/string if more info is needed","Call the function directly ({{ myFunc }}) instead of via maybe if you control error handling in-template","Add a unit test invoking the function through maybe to catch signature drift"],"exampleFix":"// before (custom template func)\nfunc (f MyFuncs) MyHelper(s string) (string, error, bool) { ... }\n\n// after\nfunc (f MyFuncs) MyHelper(s string) (string, error) { ... }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Go: compile-time guard that a template func is maybe-compatible\ntype maybeCompatible interface{}\n\nvar _ = func() struct{} {\n    // must return 0, 1, or 2 values; enforce by convention + test:\n    // reflect.TypeOf(MyFuncs.MyHelper).NumOut() <= 2\n    return struct{}{}\n}()\n\n// test:\n// n := reflect.TypeOf(MyFuncs{}).Method(0).Type.NumOut()\n// if n > 2 { t.Fatalf(\"%d return values: not maybe-compatible\", n) }","tryCatchPattern":null,"preventionTips":["Author custom template funcs with (T, error) signatures only","Add a reflection-based test asserting NumOut <= 2 for exported template funcs","Run template suites through {{ maybe }} in CI to catch signature drift"],"tags":["caddy","templates","reflection","plugins"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}