gofiber/fiber · warning

log: context tag is reserved

Error message

log: context tag is reserved

What it means

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.

Solutions

  1. Remove the "value:" entry from the CustomTags map passed to SetContextTemplate.
  2. If you need custom value rendering, register it under a different tag name (e.g. "myvalue:") and reference that tag in the format string.
  3. If the tag map is generated dynamically, filter out TagContextValue before passing it in.

Example fix

// before
SetContextTemplate(ContextConfig{
  Format: "${value} ${custom}",
  CustomTags: map[string]ContextTagFunc{
    "value:": myValueFn, // collides with reserved tag
    "custom": myCustomFn,
  },
})
// after
SetContextTemplate(ContextConfig{
  Format: "${value} ${custom}",
  CustomTags: map[string]ContextTagFunc{
    "custom": myCustomFn,
  },
})
Defensive patterns

Strategy: validation

Validate before calling

func sanitizeContextTags(in map[string]ContextTagFunc) map[string]ContextTagFunc {
    out := make(map[string]ContextTagFunc, len(in))
    for k, v := range in {
        if k == log.TagContextValue {
            continue // reserved; SetContextTemplate would reject it
        }
        out[k] = v
    }
    return out
}

Try / catch

if err := log.SetContextTemplate(cfg); err != nil {
    if errors.Is(err, log.ErrContextTagReserved) {
        // strip the reserved key from CustomTags and retry, or surface config error
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetContextTemplate(ContextConfig{CustomTags: map[string]ContextTagFunc{"value:": fn}}), or calling RegisterContextTag("value:", fn). Both paths short-circuit before mutating global state.

Common situations: 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.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/9433e456b1d96ecf. Report an issue: GitHub.

Appendix: source

Thrown at log/context.go:87

// contextTemplate holds the precompiled format. Loads on the log hot path
// happen lock-free; rebuilds (write side) hold contextMu.
var contextTemplate atomic.Pointer[logtemplate.Template[any, ContextData]]

var (
	// contextMu guards rebuilds of contextFormat / contextTags. Readers of
	// the compiled template (writeContext) use contextTemplate.Load directly.
	contextMu     sync.RWMutex
	contextFormat = DefaultFormat
	contextTags   = defaultContextTagMap()
)

var (
	// ErrContextTagInvalid is returned by RegisterContextTag and SetContextTemplate
	// when the supplied tag name or renderer is empty.
	ErrContextTagInvalid = errors.New("log: context tag name and function are required")
	// ErrContextTagReserved is returned by RegisterContextTag and SetContextTemplate
	// when the caller attempts to override the reserved TagContextValue ("value:") tag.
	ErrContextTagReserved = errors.New("log: context tag is reserved")
)

// SetContextTemplate configures contextual fields rendered by WithContext for Fiber's default logger.
// Pass an empty ContextConfig (or ContextConfig{Format: DefaultFormat}) to disable contextual fields.
// It returns an error if config.Format cannot be parsed or if config.CustomTags attempts to
// override the reserved TagContextValue tag.
func SetContextTemplate(config ContextConfig) error {
	if _, ok := config.CustomTags[TagContextValue]; ok {
		return ErrContextTagReserved
	}

	contextMu.Lock()
	defer contextMu.Unlock()

	// Cloning the live tag map preserves prior RegisterContextTag entries —
	// callers that interleave RegisterContextTag with SetContextTemplate
	// expect the registration to remain visible. CustomTags layer on top.
	tags := maps.Clone(contextTags)

View on GitHub (pinned to a105acad6c)