gofiber/fiber · error · UnknownTagError
ErrUnknownTag
ErrUnknownTag
Error message
logger: unknown template tag
What it means
logger.New compiles Config.Format into a chain of tag renderers via logtemplate.Build; if the format references a tag that has no registered renderer (e.g. ${typo} or ${reqHeader:} with an empty param), Build returns an UnknownTagError. translateBuildError converts it to the public logger.UnknownTagError (which wraps ErrUnknownTag), and logger.New panics with that typed error so the misconfiguration surfaces at startup rather than producing a silently-empty log field. The panic value supports errors.Is(err, ErrUnknownTag) and errors.As for *UnknownTagError.
Source
Thrown at middleware/logger/logger.go:84
dataPool = sync.Pool{New: func() any { return new(Data) }}
)
// Err padding starts at the documented default and grows once on first
// request to fit the longest registered route path.
errPadding := defaultErrPadding
errPaddingStr := strconv.Itoa(errPadding)
// Before handling func
cfg.BeforeHandlerFunc(&cfg)
// Logger data
// instead of analyzing the template inside(handler) each time, this is done once before
// and we create several slices of the same length with the functions to be executed and fixed parts.
template, err := logtemplate.Build[fiber.Ctx, Data](cfg.Format, createTagMap(&cfg))
if err != nil {
if translated := translateBuildError(err); translated != nil {
panic(translated)
}
panic(err)
}
templateChain, logFuncChain := template.Chains()
// Return new handler
return func(c fiber.Ctx) error {
// Don't execute middleware if Next returns true
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Set error handler once
once.Do(func() {
// get longest possible path
stack := c.App().Stack()
for m := range stack {
for r := range stack[m] {View on GitHub (pinned to a105acad6c)
Solutions
- Correct the tag name — cross-check against the Tag* constants in middleware/logger/tags.go (e.g. ${referer}, ${status}, ${method}, ${ip}, ${latency}).
- Register any custom tag with logger.MustRegisterTag BEFORE logger.New(...) compiles the format.
- Recover the typed error to introspect which tag failed: use errors.As(err, &unknownTagErr) and read unknownTagErr.Tag / unknownTagErr.Hint.
Example fix
// before — 'referer' misspelled
app.Use(logger.New(logger.Config{
Format: "${time} ${method} ${path} ${refererr}\n",
}))
// after
app.Use(logger.New(logger.Config{
Format: "${time} ${method} ${path} ${referer}\n",
})) Defensive patterns
Strategy: validation
Validate before calling
// Validate the format compiles before logger.New panics at boot.
// Easiest: boot the app in a test.
func TestLoggerFormatCompiles(t *testing.T) {
t.Parallel()
assert.NotPanics(t, func() {
app := fiber.New()
app.Use(logger.New(logger.Config{Format: yourFormat}))
_ = app
})
} Type guard
func referencesKnownTags(format string, known map[string]struct{}) (missing []string) {
for _, m := range tagRegexp.FindAllStringSubmatch(format, -1) {
if _, ok := known[m[1]]; !ok {
missing = append(missing, m[1])
}
}
return
} Try / catch
// If you must isolate the failure (e.g. plugin host), recover the typed error:
defer func() {
if r := recover(); r != nil {
var ute *logger.UnknownTagError
if errors.As(r.(error), &ute) {
log.Printf("logger format references unknown tag %q (hint: %s)", ute.Tag, ute.Hint)
}
panic(r) // re-panic otherwise
}
}()
app.Use(logger.New(logger.Config{Format: fmtStr})) Prevention
- Reference tag names from the Tag* constants, not from memory.
- Register custom/context tags before logger.New compiles the format.
- Add a boot smoke test in CI so a typo'd tag fails the build, not production.
When it happens
Trigger: Config.Format containing ${nonexistent}, a misspelled built-in tag like ${referer} (the constant is TagReferer, no second 'r'), or a parametric tag (${query:}) with an empty/invalid parameter. Custom tags referenced before MustRegisterTag runs also hit this.
Common situations: Typo in the format string; referencing a context tag (e.g. ${api-key}) before the producing middleware registered it; upgrading Fiber and hitting a renamed/removed tag; copy-pasting a format from an older version.
Related errors
- logger: RegisterContextTag requires a non-empty name and ext
- ErrTagInvalid
- logger: unknown template tag
- logger: tag name and function are required
- log: context tag is reserved
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/058f4fd661925799.
Report an issue: GitHub.