gofiber/fiber · error · ErrContextTagReserved

log: context tag is reserved

Error message

log: context tag is reserved

What it means

ErrContextTagReserved ('log: context tag is reserved', log/context.go:87) is returned by log.RegisterContextTag (log/context.go:140) and SetContextTemplate (log/context.go:96) when the caller tries to register or override the reserved tag 'value:' (TagContextValue). That tag is the built-in renderer for ${value:KEY} context-value lookups and is re-installed by Fiber itself, so user overrides are rejected to preserve its semantics.

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 9a4c7e57fe)

Solutions

  1. Choose a different, non-reserved tag name for your custom renderer (e.g. 'myvalue' or 'data:').
  2. Filter 'value:' out of any auto-generated CustomTags map before calling SetContextTemplate.
  3. To add context values, rely on the built-in ${value:KEY} tag instead of overriding it.

Example fix

// before
log.SetContextTemplate(log.ContextConfig{
    CustomTags: map[string]log.ContextTagFunc{
        "value:": myRenderer, // reserved -> ErrContextTagReserved
    },
    Format: "${value:userId}",
})

// after
log.SetContextTemplate(log.ContextConfig{
    CustomTags: map[string]log.ContextTagFunc{
        "myvalue:": myRenderer, // custom parametric tag
    },
    Format: "${myvalue:userId}",
})
Defensive patterns

Strategy: validation

Validate before calling

// Strip the reserved tag from auto-generated CustomTags.
delete(customTags, log.TagContextValue) // "value:"
if err := log.SetContextTemplate(log.ContextConfig{CustomTags: customTags, Format: fmtStr}); err != nil {
    return err
}

Try / catch

if err := log.RegisterContextTag(tag, fn); err != nil {
    if errors.Is(err, log.ErrContextTagReserved) {
        log.Printf("tag %q is reserved; rename it", tag)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Calling RegisterContextTag("value:", fn), or passing CustomTags: map[string]ContextTagFunc{"value:": fn} to SetContextTemplate. Any attempt to claim the reserved name yields this error. Must variants panic with it.

Common situations: Wanting a generic 'value' tag and not realizing 'value:' is reserved, or programmatically registering tags from a list that happens to include 'value:'. Confusing the bare vs parametric forms.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/9433e456b1d96ecf.json. Report an issue: GitHub.