hibiken/asynq · error

cannot encode nil worker info

Error message

cannot encode nil worker info

What it means

EncodeWorkerInfo marshals a *WorkerInfo (a currently-processing task's worker record) into protobuf bytes to be stored as part of server state. The library throws this when the worker info pointer is nil, since encoding an absent worker is meaningless. It prevents a nil dereference inside proto.Marshal.

Solutions

  1. Verify each *WorkerInfo is non-nil before adding it to ServerState.Workers or passing it to EncodeWorkerInfo.
  2. Fix the producer that should construct WorkerInfo (Host, PID, ID, Queue, TaskMessage fields) so it never yields nil.
  3. Filter nil entries when building the Workers slice.

Example fix

// before
workers := make([]*base.WorkerInfo, len(active))
for i, t := range active {
    workers[i] = workerMap[t.ID] // may be nil
}
// after
var workers []*base.WorkerInfo
for _, t := range active {
    if w := workerMap[t.ID]; w != nil {
        workers = append(workers, w)
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

for _, w := range workers {
    if w == nil {
        return errors.New("nil worker info in server state")
    }
}

Type guard

func validWorker(w *base.WorkerInfo) bool { return w != nil && w.ID != "" }

Try / catch

b, err := base.EncodeWorkerInfo(w)
if err != nil {
    log.Printf("skip worker %s: %v", wID, err)
    continue
}

Prevention

When it happens

Trigger: Calling base.EncodeWorkerInfo(nil) directly, or WriteServerState being handed a ServerState whose Workers slice contains a nil *WorkerInfo, or a WorkerInfo variable that was never allocated.

Common situations: Application code tracking in-flight tasks that appends pointers from a map lookup which returned nil; test code declaring `var w *base.WorkerInfo` without initialization; a task-processing hook that failed to build the WorkerInfo before heartbeating.

Related errors


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

Appendix: source

Thrown at internal/base/base.go:443

}

// WorkerInfo holds information about a running worker.
type WorkerInfo struct {
	Host     string
	PID      int
	ServerID string
	ID       string
	Type     string
	Payload  []byte
	Queue    string
	Started  time.Time
	Deadline time.Time
}

// EncodeWorkerInfo marshals the given WorkerInfo and returns the encoded bytes.
func EncodeWorkerInfo(info *WorkerInfo) ([]byte, error) {
	if info == nil {
		return nil, fmt.Errorf("cannot encode nil worker info")
	}
	startTime := timestamppb.New(info.Started)
	deadline := timestamppb.New(info.Deadline)

	return proto.Marshal(&pb.WorkerInfo{
		Host:        info.Host,
		Pid:         int32(info.PID),
		ServerId:    info.ServerID,
		TaskId:      info.ID,
		TaskType:    info.Type,
		TaskPayload: info.Payload,
		Queue:       info.Queue,
		StartTime:   startTime,
		Deadline:    deadline,
	})
}

// DecodeWorkerInfo decodes the given bytes into WorkerInfo.

View on GitHub (pinned to d135f1439b)