{"record":{"id":"9433e456b1d96ecf","repo":"gofiber/fiber","slug":"log-context-tag-is-reserved","errorCode":null,"errorMessage":"log: context tag is reserved","messagePattern":"log: context tag is reserved","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"log/context.go","lineNumber":87,"sourceCode":"// 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 —\n\t// callers that interleave RegisterContextTag with SetContextTemplate\n\t// expect the registration to remain visible. CustomTags layer on top.\n\ttags := maps.Clone(contextTags)","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/log/context.go#L69-L105","documentation":"Returned by log.SetContextTemplate and log.RegisterContextTag when a caller tries to register or override the reserved context tag TagContextValue (the \"value:\" tag). Fiber reserves that tag because it renders the default contextual value field; the framework reinstalls it after applying CustomTags so user overrides would be silently dropped. Returning the error makes the collision explicit at config time.","triggerScenarios":"Calling SetContextTemplate(ContextConfig{CustomTags: map[string]ContextTagFunc{\"value:\": fn}}), or calling RegisterContextTag(\"value:\", fn). Both paths short-circuit before mutating global state.","commonSituations":"An application that builds CustomTags programmatically (e.g. from a config file or list of tag names) and accidentally includes the literal \"value:\" key. Copy-pasting a tag map that already contained the value tag.","solutions":["Remove the \"value:\" entry from the CustomTags map passed to SetContextTemplate.","If you need custom value rendering, register it under a different tag name (e.g. \"myvalue:\") and reference that tag in the format string.","If the tag map is generated dynamically, filter out TagContextValue before passing it in."],"exampleFix":"// before\nSetContextTemplate(ContextConfig{\n  Format: \"${value} ${custom}\",\n  CustomTags: map[string]ContextTagFunc{\n    \"value:\": myValueFn, // collides with reserved tag\n    \"custom\": myCustomFn,\n  },\n})\n// after\nSetContextTemplate(ContextConfig{\n  Format: \"${value} ${custom}\",\n  CustomTags: map[string]ContextTagFunc{\n    \"custom\": myCustomFn,\n  },\n})","handlingStrategy":"validation","validationCode":"func sanitizeContextTags(in map[string]ContextTagFunc) map[string]ContextTagFunc {\n    out := make(map[string]ContextTagFunc, len(in))\n    for k, v := range in {\n        if k == log.TagContextValue {\n            continue // reserved; SetContextTemplate would reject it\n        }\n        out[k] = v\n    }\n    return out\n}","typeGuard":null,"tryCatchPattern":"if err := log.SetContextTemplate(cfg); err != nil {\n    if errors.Is(err, log.ErrContextTagReserved) {\n        // strip the reserved key from CustomTags and retry, or surface config error\n    }\n    return err\n}","preventionTips":["Never add \"value:\" to a CustomTags map by hand; treat TagContextValue as read-only.","When generating CustomTags from config, filter out reserved names before calling SetContextTemplate.","Prefer per-instance CustomTags over global RegisterContextTag to avoid collisions."],"tags":["log","config","template"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}