{"record":{"id":"4c14afd0ae3c64cb","repo":"gofiber/fiber","slug":"log-context-tag-name-and-function-are-required","errorCode":null,"errorMessage":"log: context tag name and function are required","messagePattern":"log: context tag name and function are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"log/context.go","lineNumber":84,"sourceCode":"\tFormat string\n}\n\n// contextTemplate holds the precompiled format. Loads on the log hot path\n// happen lock-free; rebuilds (write side) hold contextMu.\nvar contextTemplate atomic.Pointer[logtemplate.Template[any, ContextData]]\n\nvar (\n\t// contextMu guards rebuilds of contextFormat / contextTags. Readers of\n\t// the compiled template (writeContext) use contextTemplate.Load directly.\n\tcontextMu     sync.RWMutex\n\tcontextFormat = DefaultFormat\n\tcontextTags   = defaultContextTagMap()\n)\n\nvar (\n\t// ErrContextTagInvalid is returned by RegisterContextTag and SetContextTemplate\n\t// when the supplied tag name or renderer is empty.\n\tErrContextTagInvalid = errors.New(\"log: context tag name and function are required\")\n\t// ErrContextTagReserved is returned by RegisterContextTag and SetContextTemplate\n\t// when the caller attempts to override the reserved TagContextValue (\"value:\") tag.\n\tErrContextTagReserved = errors.New(\"log: context tag is reserved\")\n)\n\n// SetContextTemplate configures contextual fields rendered by WithContext for Fiber's default logger.\n// Pass an empty ContextConfig (or ContextConfig{Format: DefaultFormat}) to disable contextual fields.\n// It returns an error if config.Format cannot be parsed or if config.CustomTags attempts to\n// override the reserved TagContextValue tag.\nfunc SetContextTemplate(config ContextConfig) error {\n\tif _, ok := config.CustomTags[TagContextValue]; ok {\n\t\treturn ErrContextTagReserved\n\t}\n\n\tcontextMu.Lock()\n\tdefer contextMu.Unlock()\n\n\t// Cloning the live tag map preserves prior RegisterContextTag entries —","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/log/context.go#L66-L102","documentation":"ErrContextTagInvalid is returned by RegisterContextTag (log/context.go:137) when the supplied tag name is empty or the render function is nil. The doc comment also mentions SetContextTemplate, but the implementation in this revision checks only the reserved-tag condition there; the empty-name/nil-fn guard is exclusive to RegisterContextTag.","triggerScenarios":"Calling fiber.RegisterContextTag(\"\", fn) or fiber.RegisterContextTag(\"user:\", nil). The single guard at log/context.go:135-137 trips on either condition. RegisterContextTag is typically called at startup to extend the fields rendered by WithContext in the default logger.","commonSituations":"Programmatically building a tag name from data that can be empty; passing a function variable that was never assigned; refactoring a renderer and leaving a nil pointer; version drift where SetContextTemplate starts validating CustomTags entries.","solutions":["Provide a non-empty tag and a non-nil function: fiber.RegisterContextTag(\"trace:\", renderTraceID).","If the tag name is computed, validate it before calling RegisterContextTag and skip registration when empty.","Reserve the \"value:\" tag for fiber (registering it returns the sibling ErrContextTagReserved)."],"exampleFix":"// before\nif err := fiber.RegisterContextTag(tagName, nil); err != nil {\n    log.Fatal(err)\n}\n// after\nif tagName != \"\" && renderFn != nil {\n    if err := fiber.RegisterContextTag(tagName, renderFn); err != nil {\n        log.Fatal(err)\n    }\n}","handlingStrategy":"validation","validationCode":"// Validate tag and renderer before registration so the library guard\n// never fires.\nfunc registerTagSafe(name string, fn fiber.ContextTagFunc) error {\n    if name == \"\" || fn == nil {\n        return fmt.Errorf(\"context tag: name and function are required\")\n    }\n    return fiber.RegisterContextTag(name, fn)\n}","typeGuard":null,"tryCatchPattern":"if err := fiber.RegisterContextTag(name, fn); err != nil {\n    if errors.Is(err, fiber.ErrContextTagInvalid) {\n        log.Fatalf(\"context tag %q: provide a non-empty name and non-nil function\", name)\n    }\n    if errors.Is(err, fiber.ErrContextTagReserved) {\n        log.Fatalf(\"context tag %q: 'value:' is reserved\", name)\n    }\n    log.Fatal(err)\n}","preventionTips":["Validate computed tag names before calling RegisterContextTag.","Never attempt to register the reserved 'value:' tag.","Keep a startup test that registers all context tags so misconfiguration surfaces in CI."],"tags":["log","context","config","programmer-error"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}