temporalio/temporal · error

unmarshal payload for queue with type %v and name %v failed:

Error message

unmarshal payload for queue with type %v and name %v failed: %w

What it means

After the encoding check passes, extractQueueMetadata unmarshals the metadata payload blob into persistencespb.Queue. A protobuf unmarshal failure is wrapped in serialization.NewDeserializationError together with the queue type/name. This means the stored bytes are not a valid Queue proto message.

Source

Thrown at common/persistence/sql/queue_v2.go:364

	}
	return q.extractQueueMetadata(metadata)
}

func (q queueV2) extractQueueMetadata(metadataRow *sqlplugin.QueueV2MetadataRow) (*persistencespb.Queue, error) {
	if metadataRow.MetadataEncoding != enumspb.ENCODING_TYPE_PROTO3.String() {
		return nil, fmt.Errorf(
			"queue with type %v and name %v has invalid encoding: %w",
			metadataRow.QueueType,
			metadataRow.QueueName,
			serialization.NewUnknownEncodingTypeError(metadataRow.MetadataEncoding, enumspb.ENCODING_TYPE_PROTO3),
		)
	}
	qm := &persistencespb.Queue{}
	err := qm.Unmarshal(metadataRow.MetadataPayload)
	if err != nil {
		return nil, serialization.NewDeserializationError(
			enumspb.ENCODING_TYPE_PROTO3,
			fmt.Errorf("unmarshal payload for queue with type %v and name %v failed: %w",
				metadataRow.QueueType,
				metadataRow.QueueName,
				err),
		)
	}
	return qm, nil
}

func (q *queueV2) getMaxMessageID(ctx context.Context, queueType persistence.QueueV2Type, queueName string, tc sqlplugin.TableCRUD) (int64, bool, error) {
	lastMessageID, err := tc.GetLastEnqueuedMessageIDForUpdateV2(ctx, sqlplugin.QueueV2Filter{
		QueueType: queueType,
		QueueName: queueName,
		Partition: defaultPartition,
	})
	switch {
	case err == nil:
		return lastMessageID, true, nil
	case errors.Is(err, sql.ErrNoRows):

View on GitHub (pinned to bde624efd1)

Solutions

  1. Inspect the metadata row for the named queue; compare its payload against a freshly created queue's payload.
  2. Rewrite the metadata payload with a correctly marshaled persistencespb.Queue, or delete and recreate the queue.
  3. Check for schema/version skew between the code writing the payload and the code reading it; upgrade to matching versions.
  4. Restore the affected rows from a database backup if corruption is widespread.
Defensive patterns

Strategy: try-catch

Try / catch

qm, err := store.GetQueueMetadata(ctx, req)
if err != nil {
    var deserErr *serialization.DeserializationError
    if errors.As(err, &deserErr) {
        // metadata blob corrupt; recreate queue or restore from backup
    }
    return err
}

Prevention

When it happens

Trigger: getQueueMetadata or getMessageCountAndLastID loads a metadata row whose MetadataPayload bytes fail qm.Unmarshal — truncated, corrupt, or not a Queue proto.

Common situations: Corrupted or truncated blob in the database; payload written by an incompatible proto schema version; manual DB manipulation; storage-layer bit rot.

Related errors


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