temporalio/temporal · error
remaining actions cannot be negative
Error message
remaining actions cannot be negative
What it means
Validation error from validateScheduleRemainingActions: a Schedule's state reports a negative RemainingActions count. RemainingActions tracks how many more actions the schedule may take (for limited schedules) and must be >= 0; a negative value indicates corrupted schedule state.
Source
Thrown at service/frontend/workflow_handler.go:7046
func validateScheduleTimestamps(spec *schedulepb.ScheduleSpec) error {
if err := validateTimestamp(spec.GetStartTime(), "start time"); err != nil {
return err
}
return validateTimestamp(spec.GetEndTime(), "end time")
}
func validateTimestamp(value *timestamppb.Timestamp, field string) error {
if value != nil {
if err := value.CheckValid(); err != nil {
return fmt.Errorf("%s is not a valid timestamp: %w", field, err)
}
}
return nil
}
func validateScheduleRemainingActions(schedule *schedulepb.Schedule) error {
if schedule.GetState().GetRemainingActions() < 0 {
return errors.New("remaining actions cannot be negative")
}
return nil
}
func validateScheduleOverlapPolicy(policy enumspb.ScheduleOverlapPolicy, field string) error {
if _, ok := enumspb.ScheduleOverlapPolicy_name[int32(policy)]; !ok {
return fmt.Errorf("%s has unsupported overlap policy %v", field, policy)
}
return nil
}
func (wh *WorkflowHandler) validateScheduleOverlapPolicies(
schedule *schedulepb.Schedule,
patch *schedulepb.SchedulePatch,
namespaceName string,
) error {
if schedule != nil {
if err := validateScheduleOverlapPolicy(schedule.GetPolicies().GetOverlapPolicy(), "schedule policies"); err != nil {View on GitHub (pinned to bde624efd1)
Solutions
- Inspect the schedule state and set RemainingActions to a correct non-negative value (0 for exhausted, unset/unlimited appropriately)
- If state is corrupted, update the schedule via UpdateSchedule with correct limits rather than importing raw state
- Check the version that produced the schedule for known decrement bugs and upgrade
Example fix
// before (crafted schedule state) schedule.State.RemainingActions = -1 // after schedule.State.RemainingActions = 0 // or omit for unlimited
Defensive patterns
Strategy: validation
Validate before calling
if schedule.GetState().GetRemainingActions() < 0 {
return errors.New("remaining actions must be >= 0")
} Prevention
- Never import or hand-craft schedule state with negative counters
- Validate schedule updates client-side before calling UpdateSchedule
- Keep the server version current to benefit from schedule state bug fixes
When it happens
Trigger: Validate/Update or schedule-related API calls that supply or persist a schedule whose State.RemainingActions is negative, e.g. via UpdateSchedule with crafted state, or restored/corrupted schedule records.
Common situations: Importing schedule state from backups or other clusters, off-by-one bugs when decrementing remaining actions in old versions, or hand-crafted workflow update requests.
Related errors
- interval is not a valid duration: %w
- phase is not a valid duration: %w
- %s is not a valid timestamp: %w
- %s has unsupported overlap policy %v
- link type is empty
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/6137c3f7babbd6b8.
Report an issue: GitHub.