temporalio/temporal · warning
root task queue partition has no parent
Error message
root task queue partition has no parent
What it means
ErrNoParent is the sentinel error returned when Parent() is called on the root partition of a task-queue family. The root partition (partition 0 of the root task queue) sits at the top of the tqid partition tree, so it has no parent by construction. Test helpers and user-data lookup use it to detect when upward traversal must stop or is invalid.
Source
Thrown at common/tqid/task_queue_id.go:123
}
// PartitionKey uniquely identifies a task queue partition, to be used in maps.
// Note that task queue kind (sticky vs normal) and normal name for sticky task queues are not
// part of the task queue partition identity.
PartitionKey struct {
namespaceId string
name string
partitionId int
taskType enumspb.TaskQueueType
}
)
var _ Partition = (*NormalPartition)(nil)
var _ Partition = (*StickyPartition)(nil)
var _ Partition = (*WorkerCommandsPartition)(nil)
var (
ErrNoParent = errors.New("root task queue partition has no parent")
ErrInvalidDegree = errors.New("invalid task queue partition branching degree")
ErrNonZeroSticky = errors.New("only sticky partitions can not have non-zero partition ID")
)
// NewTaskQueueFamily takes a user-provided task queue name (aka family name) and returns a TaskQueueFamily. Returns an
// error if name looks like a mangled name.
func NewTaskQueueFamily(namespaceId string, name string) (*TaskQueueFamily, error) {
if strings.HasPrefix(name, nonRootPartitionPrefix) {
return nil, serviceerror.NewInvalidArgument("task queue family name cannot have prefix /_sys/ " + name)
}
return &TaskQueueFamily{
namespaceId: namespaceId,
name: name,
}, nil
}
// UnsafeTaskQueueFamily returns a TaskQueueFamily object without validating the task queue name.
// This method should only be used in logs/metrics, not in the server logic (use NewTaskQueueFamily instead).View on GitHub (pinned to bde624efd1)
Solutions
- Stop traversal when Parent() returns ErrNoParent — treat it as the root sentinel via errors.Is(err, tqid.ErrNoParent)
- Check partition ID before calling Parent(): skip the call when the partition is the root (partition ID 0 of the root task queue)
- Fix partition math so routing only forwards when a parent partition actually exists
Example fix
// before
parent, err := partition.Parent()
require.NoError(t, err)
// after
parent, err := partition.Parent()
if errors.Is(err, tqid.ErrNoParent) {
return // already at root
}
require.NoError(t, err) Defensive patterns
Strategy: try-catch
Validate before calling
if partition.ID() == 0 && partition.TaskQueue().Parent() == nil /* root family */ {
// skip Parent() call
} Type guard
func hasParent(p tqid.Partition) bool {
_, err := p.Parent()
return !errors.Is(err, tqid.ErrNoParent)
} Try / catch
parent, err := partition.Parent()
if errors.Is(err, tqid.ErrNoParent) {
return // root reached; stop upward traversal
}
if err != nil {
return err
} Prevention
- Always check errors.Is(err, tqid.ErrNoParent) to detect the root
- Stop parent-walking loops on ErrNoParent
- Validate partition IDs before computing parents
When it happens
Trigger: Calling Parent() on the root NormalPartition of a TaskQueueFamily; userDataFetchSource walking to parents past the root; tests like TestForwardTaskError/TestForwardQueryTaskError/TestForwardPollError exercising forwarding beyond the root partition.
Common situations: Partition-index arithmetic that computes partition 0 (root) and still requests a parent; recursive algorithms lacking a root stop condition; forwarding logic trying to route a task/query to a nonexistent parent queue.
Related errors
- page size to read history tasks must be positive
- history task from queue has nil blob
- enqueue task request task is nil
- queue already exists
- shard ID must be greater than 0
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/5924717bfb9d4bd4.
Report an issue: GitHub.