hibiken/asynq · error
cannot encode nil message
Error message
cannot encode nil message
What it means
base.EncodeMessage rejects a nil *TaskMessage before attempting protobuf marshaling, returning 'cannot encode nil message'. Encoding a nil message would otherwise panic or produce a meaningless empty payload, so the library fails with an explicit error.
Solutions
- Check msg != nil before calling EncodeMessage and return a descriptive error early.
- Validate every element of a batch before enqueuing; skip or fail loudly on nil entries.
- Fix the constructor/builder that produced the nil message instead of guarding at the encode site.
- Use asynq.NewTask(...).Message() (higher-level API) so a nil message cannot be constructed accidentally.
Example fix
// before
payload, _ := base.EncodeMessage(msg)
// after
if msg == nil { return fmt.Errorf("task message not initialized") }
payload, err := base.EncodeMessage(msg) Defensive patterns
Strategy: type-guard
Validate before calling
if msg == nil { return nil, fmt.Errorf("cannot encode nil message") } Type guard
func msgReady(m *base.TaskMessage) bool { return m != nil && m.ID != "" && m.Type != "" && m.Queue != "" } Prevention
- Never append nil *TaskMessage to batches; filter first
- Construct messages via asynq.NewTask so nils are impossible
- Check builder functions for nil-return-on-error and handle before encoding
When it happens
Trigger: Calling base.EncodeMessage(nil) directly, or indirectly via Enqueue/BatchEnqueue paths where a nil message was constructed (e.g. building a TaskMessage from a task whose fields were never populated and a nil deref-guard path hit).
Common situations: Custom enqueue code assembling TaskMessage structs where a nil pointer slips into a slice used for BatchEnqueue; reflection/generic helpers returning nil on error but the caller proceeding anyway.
Related errors
- batch enqueue does not support group tasks
- batch enqueue does not support unique tasks
- redis connection is shared so the Inspector can't be closed…
- asynq
- asynq
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/a28cbedf94303738.
Report an issue: GitHub.
Appendix: source
Thrown at internal/base/base.go:305
// GroupKey holds the group key used for task aggregation.
//
// Empty string indicates no aggregation is used for this task.
GroupKey string
// Retention specifies the number of seconds the task should be retained after completion.
Retention int64
// CompletedAt is the time the task was processed successfully in Unix time,
// the number of seconds elapsed since January 1, 1970 UTC.
//
// Use zero to indicate no value.
CompletedAt int64
}
// EncodeMessage marshals the given task message and returns an encoded bytes.
func EncodeMessage(msg *TaskMessage) ([]byte, error) {
if msg == nil {
return nil, fmt.Errorf("cannot encode nil message")
}
return proto.Marshal(&pb.TaskMessage{
Type: msg.Type,
Payload: msg.Payload,
Headers: msg.Headers,
Id: msg.ID,
Queue: msg.Queue,
Retry: int32(msg.Retry),
Retried: int32(msg.Retried),
ErrorMsg: msg.ErrorMsg,
LastFailedAt: msg.LastFailedAt,
Timeout: msg.Timeout,
Deadline: msg.Deadline,
UniqueKey: msg.UniqueKey,
GroupKey: msg.GroupKey,
Retention: msg.Retention,
CompletedAt: msg.CompletedAt,
})View on GitHub (pinned to d135f1439b)