{"record":{"id":"968ca857d1ec7719","repo":"temporalio/temporal","slug":"task-has-no-deadline-or-destination","errorCode":null,"errorMessage":"task has no deadline or destination","messagePattern":"task has no deadline or destination","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/history/workflow/task_generator.go","lineNumber":1005,"sourceCode":"\t// NOTE: at the moment deadline is mutually exclusive with destination.\n\t// This will change when we add the outbound timer queue.\n\tif task.Deadline() != hsm.Immediate {\n\t\tif task.Destination() != \"\" {\n\t\t\t// TODO: support outbound timer tasks.\n\t\t\treturn fmt.Errorf(\"task cannot have both a deadline and destination due to missing outbound timer queue implementation\")\n\t\t}\n\t\tTrackStateMachineTimer(mutableState, task.Deadline(), taskInfo)\n\t} else if task.Destination() != \"\" {\n\t\tmutableState.AddTasks(&tasks.StateMachineOutboundTask{\n\t\t\tStateMachineTask: tasks.StateMachineTask{\n\t\t\t\tWorkflowKey: mutableState.GetWorkflowKey(),\n\t\t\t\tInfo:        taskInfo,\n\t\t\t},\n\t\t\tDestination: task.Destination(),\n\t\t})\n\t} else {\n\t\t// TODO: support \"transfer\" tasks - immediate without destination.\n\t\treturn fmt.Errorf(\"task has no deadline or destination\")\n\t}\n\n\treturn nil\n}\n\nfunc deleteStateMachineTimersByPath(execInfo *persistencespb.WorkflowExecutionInfo, path []hsm.Key) {\n\ttrimmedTimers := make([]*persistencespb.StateMachineTimerGroup, 0, len(execInfo.StateMachineTimers))\n\n\tfor _, group := range execInfo.StateMachineTimers {\n\t\ttrimmedInfos := make([]*persistencespb.StateMachineTaskInfo, 0, len(group.Infos))\n\t\tfor _, info := range group.GetInfos() {\n\t\t\tif !isPathAffectedByDelete(path, info.GetRef().GetPath()) {\n\t\t\t\ttrimmedInfos = append(trimmedInfos, info)\n\t\t\t}\n\t\t}\n\t\tif len(trimmedInfos) > 0 {\n\t\t\ttrimmedTimers = append(trimmedTimers, &persistencespb.StateMachineTimerGroup{\n\t\t\t\tInfos:     trimmedInfos,","sourceCodeStart":987,"sourceCodeEnd":1023,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/history/workflow/task_generator.go#L987-L1023","documentation":"This error is returned by the Temporal history service's HSM (hierarchical state machine) task generator when a sub-state machine task being generated has neither a deadline nor a destination. The task generator can only schedule tasks that expire by deadline or are routed to a destination; 'transfer' style tasks (immediate, without destination) are not yet implemented, as noted by the in-code TODO.","triggerScenarios":"A dirty sub-state machine is processed (via GenerateDirtySubStateMachineTasks or refreshTasksForSubStateMachines) and the task's Task() implementation returns an empty/nil Deadline and its Destination() returns empty, while Generate() produced taskInfo; generateSubStateMachineTask then hits the else branch and returns this error.","commonSituations":"Developers adding a new HSM state machine task type that returns a spec with no Deadline and no Destination, or refactoring Task()/Destination() so the deadline is dropped; also seen on upgraded clusters running new custom task definitions against a history service that lacks transfer-task support.","solutions":["Give the task a deadline: return a non-nil time.Time from the task's Deadline() (or set TaskInfo.DeadTime) so it is scheduled as a deadline-based task","Give the task a destination: make Destination() return a valid destination string so it is scheduled as a destination-based task","If the task truly must run immediately without destination, do not use this mechanism yet — transfer tasks are unsupported (TODO in task_generator.go); model it as a deadline task with a near-immediate deadline","Upgrade Temporal server if a newer version added transfer-task support for this code path"],"exampleFix":"// before (task spec without deadline or destination)\nfunc (t *myTask) Destination() string { return \"\" }\nfunc (t *myTask) Deadline() time.Time  { return time.Time{} }\n\n// after (deadline-based task)\nfunc (t *myTask) Destination() string { return \"\" }\nfunc (t *myTask) Deadline() time.Time  { return t.execTime }","handlingStrategy":"validation","validationCode":"// Validate the task spec before registering/generating it\nfunc validateTaskSpec(t hsm.Task) error {\n\tif t.Deadline().IsZero() && t.Destination() == \"\" {\n\t\treturn fmt.Errorf(\"task %T must define a deadline or destination\", t)\n\t}\n\treturn nil\n}","typeGuard":"func hasSchedule(t hsm.Task) bool {\n\treturn !t.Deadline().IsZero() || t.Destination() != \"\"\n}","tryCatchPattern":null,"preventionTips":["Always implement either Deadline() or Destination() (or both) on every HSM task type","Write a unit test asserting every registered task type yields a non-zero deadline or destination","Do not attempt immediate/no-destination transfer tasks until the server supports them","Review task spec changes in upgrades to ensure deadlines are preserved"],"tags":["go","hsm","state-machine","temporal-server","task-scheduling"],"backgroundTag":"hsm-task-missing-deadline-or-destination","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}