hibiken/asynq · error

cannot encode nil server info

Error message

cannot encode nil server info

What it means

EncodeServerInfo marshals a *ServerInfo into protobuf bytes for persisting server state in Redis. The library throws this error when the caller passes a nil pointer, because there is no meaningful encoding of a missing server record. It is a defensive guard against a nil argument that would otherwise panic inside proto marshaling.

Solutions

  1. Check that the *base.ServerInfo passed to EncodeServerInfo/WriteServerState is non-nil before calling; construct it with a proper literal (Host, PID, Concurrency, Queues, Started).
  2. If the info comes from a constructor, handle its error path instead of propagating a nil pointer.
  3. In tests, allocate the struct (e.g. info := &base.ServerInfo{...}) rather than declaring a bare var of pointer type.

Example fix

// before
var info *base.ServerInfo
err := WriteServerState(info) // cannot encode nil server info
// after
info := &base.ServerInfo{
    Host: "localhost",
    PID:  os.Getpid(),
    Concurrency: 10,
    Queues: map[string]int{"default": 1},
    Started: time.Now(),
}
err := WriteServerState(info)
Defensive patterns

Strategy: validation

Validate before calling

if info == nil {
    info = &base.ServerInfo{
        Host: host,
        PID: os.Getpid(),
        Concurrency: concurrency,
        Queues: queues,
        Started: time.Now(),
    }
}
err := base.EncodeServerInfo(info)

Type guard

func serverInfoOk(info *base.ServerInfo) bool { return info != nil && info.Queues != nil }

Try / catch

b, err := base.EncodeServerInfo(info)
if err != nil {
    return fmt.Errorf("encode server info: %w", err)
}

Prevention

When it happens

Trigger: Calling base.EncodeServerInfo(nil) directly, or WriteServerState reaching a call site where the *base.ServerInfo constructed by the caller is nil (e.g. a constructor that failed silently or a struct pointer never assigned).

Common situations: Building the ServerInfo from config where a setup function returns nil on partial failure; tests constructing server state manually and forgetting to allocate the struct; refactors that change a value-returning constructor to a pointer-returning one that can return nil.

Related errors


AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07). Data as JSON: /api/errors/0db17d46c59b4194. Report an issue: GitHub.

Appendix: source

Thrown at internal/base/base.go:381

}

// ServerInfo holds information about a running server.
type ServerInfo struct {
	Host              string
	PID               int
	ServerID          string
	Concurrency       int
	Queues            map[string]int
	StrictPriority    bool
	Status            string
	Started           time.Time
	ActiveWorkerCount int
}

// EncodeServerInfo marshals the given ServerInfo and returns the encoded bytes.
func EncodeServerInfo(info *ServerInfo) ([]byte, error) {
	if info == nil {
		return nil, fmt.Errorf("cannot encode nil server info")
	}
	queues := make(map[string]int32, len(info.Queues))
	for q, p := range info.Queues {
		queues[q] = int32(p)
	}
	started := timestamppb.New(info.Started)

	return proto.Marshal(&pb.ServerInfo{
		Host:              info.Host,
		Pid:               int32(info.PID),
		ServerId:          info.ServerID,
		Concurrency:       int32(info.Concurrency),
		Queues:            queues,
		StrictPriority:    info.StrictPriority,
		Status:            info.Status,
		StartTime:         started,
		ActiveWorkerCount: int32(info.ActiveWorkerCount),
	})

View on GitHub (pinned to d135f1439b)