gofiber/fiber · error

log: context tag name and function are required

Error message

log: context tag name and function are required

What it means

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.

Solutions

  1. Provide a non-empty tag and a non-nil function: fiber.RegisterContextTag("trace:", renderTraceID).
  2. If the tag name is computed, validate it before calling RegisterContextTag and skip registration when empty.
  3. Reserve the "value:" tag for fiber (registering it returns the sibling ErrContextTagReserved).

Example fix

// before
if err := fiber.RegisterContextTag(tagName, nil); err != nil {
    log.Fatal(err)
}
// after
if tagName != "" && renderFn != nil {
    if err := fiber.RegisterContextTag(tagName, renderFn); err != nil {
        log.Fatal(err)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate tag and renderer before registration so the library guard
// never fires.
func registerTagSafe(name string, fn fiber.ContextTagFunc) error {
    if name == "" || fn == nil {
        return fmt.Errorf("context tag: name and function are required")
    }
    return fiber.RegisterContextTag(name, fn)
}

Try / catch

if err := fiber.RegisterContextTag(name, fn); err != nil {
    if errors.Is(err, fiber.ErrContextTagInvalid) {
        log.Fatalf("context tag %q: provide a non-empty name and non-nil function", name)
    }
    if errors.Is(err, fiber.ErrContextTagReserved) {
        log.Fatalf("context tag %q: 'value:' is reserved", name)
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: 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.

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

Related errors


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

Appendix: source

Thrown at log/context.go:84

	Format string
}

// 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 —

View on GitHub (pinned to a105acad6c)