{"record":{"id":"60e6c121dbebe14f","repo":"gofiber/fiber","slug":"errtaginvalid","errorCode":"ErrTagInvalid","errorMessage":"logger: tag name and function are required","messagePattern":"logger: tag name and function are required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/logger/tags.go","lineNumber":85,"sourceCode":"// Registered tags are available to logger middleware instances created after\n// registration and can be overridden per instance with Config.CustomTags.\n// Re-registering a tag replaces the existing tag function.\nfunc RegisterTag(tag string, fn LogFunc) error {\n\tif tag == \"\" || fn == nil {\n\t\treturn ErrTagInvalid\n\t}\n\n\tregisteredTags.Lock()\n\tdefer registeredTags.Unlock()\n\n\tregisteredTags.m[tag] = fn\n\treturn nil\n}\n\n// MustRegisterTag registers a global logger middleware tag and panics on failure.\nfunc MustRegisterTag(tag string, fn LogFunc) {\n\tif err := RegisterTag(tag, fn); err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// createTagMap function merged the default with the custom tags\nfunc createTagMap(cfg *Config) map[string]LogFunc {\n\t// Set default tags\n\ttagFunctions := map[string]LogFunc{\n\t\tTagReferer: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) {\n\t\t\treturn writeSanitizedString(output, c.Get(fiber.HeaderReferer))\n\t\t},\n\t\tTagProtocol: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) {\n\t\t\treturn output.WriteString(c.Protocol())\n\t\t},\n\t\tTagScheme: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) {\n\t\t\t// Scheme echoes X-Forwarded-Proto / X-Url-Scheme once the proxy is\n\t\t\t// trusted, so it is request-derived like ${ips} and ${ua}.\n\t\t\treturn writeSanitizedString(output, c.Scheme())\n\t\t},","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/logger/tags.go#L67-L103","documentation":"logger.RegisterTag returns ErrTagInvalid (\"logger: tag name and function are required\") and MustRegisterTag panics with that error when tag is empty or fn is nil. The tag registry needs both a non-empty name and a non-nil renderer; otherwise the tag could never produce output and would shadow/overwrite valid registrations ambiguously.","triggerScenarios":"logger.MustRegisterTag(\"\", fn), logger.MustRegisterTag(\"foo\", nil), or RegisterTag used directly with the error ignored and later New() failing because the tag was never actually stored.","commonSituations":"Registering tags in a loop over user config where a name is empty; a LogFunc built by a helper that returns nil on an error branch; refactor that accidentally passes the function in the wrong argument position.","solutions":["Pass a non-empty tag name and a non-nil LogFunc to MustRegisterTag.","Skip empty/nil entries: if name != \"\" && fn != nil { logger.MustRegisterTag(name, fn) }.","When using RegisterTag (non-Must), check the returned error and log/handle it instead of ignoring."],"exampleFix":"// before\nlogger.MustRegisterTag(\"\", func(output logger.Buffer, c fiber.Ctx, _ *logger.Data, _ string) (int, error) {\n    return output.WriteString(\"x\")\n})\n\n// after\nlogger.MustRegisterTag(\"tenant\", func(output logger.Buffer, c fiber.Ctx, _ *logger.Data, _ string) (int, error) {\n    return output.WriteString(c.Locals(\"tenant\").(string))\n})","handlingStrategy":"validation","validationCode":"func safeRegisterTag(name string, fn logger.LogFunc) error {\n    if name == \"\" || fn == nil {\n        return logger.ErrTagInvalid\n    }\n    return logger.RegisterTag(name, fn)\n}","typeGuard":"func isValidTagRegistration(name string, fn logger.LogFunc) bool {\n    return name != \"\" && fn != nil\n}","tryCatchPattern":null,"preventionTips":["Use RegisterTag and handle its error rather than MustRegisterTag when input is dynamic.","Skip empty/nil entries in registration loops.","Validate the (name, fn) pair at the config table source."],"tags":["logger","tag-registry","config","startup-panic"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}