temporalio/temporal · error

history task from queue has nil blob

Error message

history task from queue has nil blob

What it means

ErrHistoryTaskBlobIsNil (common/persistence/history_task_queue_manager.go:42) is returned by ReadTasks when a raw history task read from the queue has a nil Blob. The queue stores tasks as serialized blobs; a nil blob cannot be deserialized, so ReadTasks wraps the failure in a serialization.NewDeserializationError with ENCODING_TYPE_PROTO3. This indicates corrupted or improperly persisted task data in the queue.

Source

Thrown at common/persistence/history_task_queue_manager.go:42

	// ErrMsgDeserializeRawHistoryTask is returned when the raw task cannot be deserialized from the task queue. This error
	// is returned when this whole top-level proto cannot be deserialized.
	//  Raw Task (a proto): <-- when this cannot be deserialized
	//	- ShardID
	//	- Blob (a serialized task)
	ErrMsgDeserializeRawHistoryTask = "failed to deserialize raw history task from task queue"
	// ErrMsgDeserializeHistoryTask is returned when the history task cannot be deserialized from the task queue. This
	// error is returned when the blob inside the raw task cannot be deserialized.
	//  Raw Task (a proto):
	//	- ShardID
	//	- Blob (a serialized task) <-- when this cannot be deserialized
	ErrMsgDeserializeHistoryTask = "failed to deserialize history task blob"
	// ErrMsgFailedToParseCategoryID is returned when category id cannot be parsed as an integer value.
	ErrMsgFailedToParseCategoryID = "failed to parse category id from queue name"
)

var (
	ErrReadTasksNonPositivePageSize = errors.New("page size to read history tasks must be positive")
	ErrHistoryTaskBlobIsNil         = errors.New("history task from queue has nil blob")
	ErrEnqueueTaskRequestTaskIsNil  = errors.New("enqueue task request task is nil")
	ErrQueueAlreadyExists           = errors.New("queue already exists")
	ErrShardIDInvalid               = errors.New("shard ID must be greater than 0")
	ErrInvalidQueueName             = errors.New("invalid queue name, expected 4 fields")
)

func NewHistoryTaskQueueManager(
	queue QueueV2,
	serializer serialization.Serializer,
) *HistoryTaskQueueManagerImpl {
	return &HistoryTaskQueueManagerImpl{
		queue:      queue,
		serializer: serializer,
	}
}

func (m *HistoryTaskQueueManagerImpl) EnqueueTask(
	ctx context.Context,

View on GitHub (pinned to bde624efd1)

Solutions

  1. Delete/skip the corrupt task record and let the task be re-enqueued or regenerated by its producer (history service)
  2. Inspect the queue's underlying persistence rows to find how many tasks have nil blobs and check recent writer versions
  3. Upgrade/fix the writer path that persisted tasks without blobs
  4. Acknowledge the task via ack manager so the poison record does not block the queue's read pointer

Example fix

// producer side: before
queue.EnqueueTask(ctx, &persistence.Task{TaskID: id}) // blob never set
// after
data, err := serializer.SerializeHistoryTask(task)
if err != nil { return err }
queue.EnqueueTask(ctx, &persistence.Task{TaskID: id, Blob: data})
Defensive patterns

Strategy: type-guard

Type guard

func isNilBlobErr(err error) bool {
    var de *serialization.DataError
    return errors.As(err, &de) && strings.Contains(err.Error(), persistence.ErrHistoryTaskBlobIsNil.Error())
}

Try / catch

tasks, err := mgr.ReadTasks(ctx, req)
if err != nil {
    if isNilBlobErr(err) {
        logger.Error("nil-blob history task encountered; acking to skip poison record", tag.Error(err))
        return ackAndSkip(err) // advance past corrupt record
    }
    return err
}

Prevention

When it happens

Trigger: Calling HistoryTaskQueueManagerImpl.ReadTasks (or ReadRawTasks feeding it) and encountering a queue record whose Blob field is nil, at history_task_queue_manager.go:159.

Common situations: Storage records written by an older/buggy writer version; data corruption in the queue's underlying persistence; manual edits or partial writes to the tasks table; replication issues leaving incomplete task rows.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/00a6d009fb6e2bee. Report an issue: GitHub.