temporalio/temporal · error

Found key with non-zero pending task count but has no corres

Error message

Found key with non-zero pending task count but has no correspoding Slice

What it means

This panic fires in findSliceToClear when the priority queue reports a key with a non-zero pending task count, but the internal slicesPerKey map has no Slice registered for that key. It is an internal invariant violation in the queue's bookkeeping: the pending-task counter and the slice registry are out of sync. The typo "correspoding" is in the original panic message.

Source

Thrown at service/history/queues/action_pending_task_count.go:140

	// order key by # of pending tasks
	keys := make([]any, 0, len(a.tasksPerKey))
	for key, keyPendingTasks := range a.tasksPerKey {
		currentPendingTasks += keyPendingTasks
		keys = append(keys, key)
	}
	pq := collection.NewPriorityQueueWithItems(
		func(this, that any) bool {
			return a.tasksPerKey[this] > a.tasksPerKey[that]
		},
		keys,
	)

	for currentPendingTasks > targetPendingTasks && !pq.IsEmpty() {
		key := pq.Remove()

		sliceList := a.slicesPerKey[key]
		if len(sliceList) == 0 {
			panic("Found key with non-zero pending task count but has no correspoding Slice")
		}

		// pop the first slice in the list
		sliceToClear := sliceList[0]
		sliceList = sliceList[1:]
		a.slicesPerKey[key] = sliceList

		tasksCleared := a.pendingTasksPerKeyPerSlice[sliceToClear][key]
		a.tasksPerKey[key] -= tasksCleared
		currentPendingTasks -= tasksCleared
		if a.tasksPerKey[key] > 0 {
			pq.Add(key)
		}

		a.keysToClearPerSlice[sliceToClear] = append(a.keysToClearPerSlice[sliceToClear], key)
	}
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Find where slices are removed/cleared from a.slicesPerKey and ensure the corresponding pending task count key is removed from the priority queue at the same time
  2. Verify the key type used for pq and slicesPerKey matches exactly (task key comparison semantics)
  3. Upgrade to a version containing the fix if this is a known temporal history invariant bug
  4. Capture the key, pending count, and pq state in logs before the panic to file a reproducible report

Example fix

// before
sliceList := a.slicesPerKey[key]
if len(sliceList) == 0 {
    panic("Found key with non-zero pending task count but has no correspoding Slice")
}
// after
sliceList := a.slicesPerKey[key]
if len(sliceList) == 0 {
    a.logger.Error("invariant violated: key in pending-task queue has no slices",
        tag.Key(key), tag.PendingTaskCount(currentPendingTasks))
    continue
}
Defensive patterns

Strategy: validation

Validate before calling

if sliceList, ok := action.slicesPerKey[key]; !ok || len(sliceList) == 0 {
    // do not invoke the clear path for this key
    return
}

Prevention

When it happens

Trigger: Run calls findSliceToClear to reduce pending tasks; pq.Remove() returns a key whose slicesPerKey entry is empty or missing because slices were cleared/removed without decrementing their pending task counts, or a slice was registered under a different key.

Common situations: Custom or modified queue actions that clear slices directly; bugs in Slice removal paths that forget to update slicesPerKey or the pending task counter; race conditions if the action is used outside the single-threaded context it was designed for.

Related errors


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