uber-go/zap · error
can't unmarshal a nil *Level
Error message
can't unmarshal a nil *Level
What it means
zapcore.Level.UnmarshalText on a nil *Level cannot store the parsed result anywhere, so it returns the sentinel errUnmarshalNilLevel. This guard exists because the pointer receiver would otherwise dereference nil.
Source
Thrown at zapcore/level.go:29
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package zapcore
import (
"bytes"
"errors"
"fmt"
)
var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level")
// A Level is a logging priority. Higher levels are more important.
type Level int8
const (
// DebugLevel logs are typically voluminous, and are usually disabled in
// production.
DebugLevel Level = iota - 1
// InfoLevel is the default logging priority.
InfoLevel
// WarnLevel logs are more important than Info, but don't need individual
// human review.
WarnLevel
// ErrorLevel logs are high-priority. If an application is running smoothly,
// it shouldn't generate any error-level logs.
ErrorLevel
// DPanicLevel logs are particularly important errors. In development the
// logger panics after writing the message.View on GitHub (pinned to bbd4ecbd87)
Solutions
- Declare a value zapcore.Level and call l.UnmarshalText(...) on its address: (&l).UnmarshalText(...)
- Ensure the enclosing struct's *Level field is non-nil before calling its Unmarshal methods
Example fix
// before
var l *zapcore.Level
l.UnmarshalText([]byte("info"))
// after
var l zapcore.Level
err := l.UnmarshalText([]byte("info")) Defensive patterns
Strategy: type-guard
Validate before calling
var lvl zapcore.Level
if err := lvl.UnmarshalText([]byte(s)); err != nil {
return err
} Type guard
func unmarshalLevel(s string) (zapcore.Level, error) {
var l zapcore.Level
if err := l.UnmarshalText([]byte(s)); err != nil {
return 0, err
}
return l, nil
} Try / catch
var l zapcore.Level
if err := l.UnmarshalText(data); err != nil {
return fmt.Errorf("parse level: %w", err)
} Prevention
- Never declare *Level just to call its Unmarshal methods; use a value
- Check struct *Level fields for nil before invoking methods
- When unmarshaling config, use zapcore.Level values or initialize pointers first
When it happens
Trigger: var l *zapcore.Level; l.UnmarshalText([]byte("info")) — calling UnmarshalText (or UnmarshalJSON, which routes through it) through a nil pointer.
Common situations: Unmarshaling config structs where the Level field pointer is nil and code calls its method directly; reflection-based decoders invoking methods on nil pointer fields.
Related errors
- invalid increase level, as level %q is allowed by increased
- missing Level
- no encoder name specified
- missing EncodeTime in EncoderConfig
- must specify logging level
AI-assisted analysis of uber-go/zap@bbd4ecbd87 (2026-08-31).
Data as JSON: /api/errors/e50bf4ca3b9ab91e.
Report an issue: GitHub.