AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウトに対応したので試してみた
はじめに
AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウトに対応しました。タスクごとに最大実行時間を指定できるようになり、指定時間を超えるとタスクが停止できるようになりました。sleep 600 するだけの WDL タスクに omicsTimeout: "2m" を指定して実行し、実際に停止するまでの挙動を確認しました。

確認結果
検証は東京リージョン(ap-northeast-1)で 2026 年 8 月 4 日に実施しました。
omicsTimeout: "2m"を指定したタスクは指定時間の経過後に停止し、run とタスクのステータスがFAILEDになりました- タスクの
startTimeからstopTimeまでは 182.274 秒 でした。指定した 120 秒に対して、停止処理に 約 62 秒 のオーバーヘッドがありました - タイムアウトを示す文言は CloudWatch Logs には出力されず、
get-run-taskのfailureReasonとコンソールの「エラーの理由」で確認できました
なにが嬉しいのか
開発中の無限ループタスクを自動停止してコストを抑えられる
ワークフローの新規作成中(試行錯誤中)に想定より長く動くタスクや無限ループに気づかないまま計算コストが高くなってしまうことがあります。omicsTimeout を runtime セクションに 1 行加えるだけで、指定時間を超えたタスクを強制的に止められようになりました。試行錯誤している段階では分単位でタスクを止められるガードレールの設定は実用的なのではないでしょうか。
run 全体でなくタスク単位でタイムアウトを区切れる
HealthOmics にはすでに run 全体の最大実行時間を決めるクォータや、run グループ単位の時間指定があります。今回追加されたomicsTimeout は、タスク単位というより小さい単位でタイムアウトを設定できます。つまり、特定のステップだけが長時間化しやすいワークフローで、特定のタスクだけにタイムアウトを設定できます。
AWS HealthOmics は 2025 年 8 月に、Nextflow の time directive で同様の仕組みを先行してサポートしていました。今回の対応で、WDL のワークフローでも同じガードレールを使えるようになりました。
omicsTimeout の仕様
omicsTimeout は WDL タスクの runtime セクションに追加する、HealthOmics 独自の属性です。整数(秒)、または s、m、h、d を組み合わせた文字列で最大実行時間を指定します。例えば "40m"、"1h30m"、"1m3s" のように書けます。
HealthOmics provides a custom
omicsTimeoutattribute to set a maximum task duration in your workflow. Specify the timeout duration as an integer (seconds) or a string using one or more of the following units:s,m,h, ord. For example,"40m","1h30m", or"1m3s".
公式ドキュメントではomicsTimeout について以下の挙動が挙げられています。
- 粒度は 1 分単位で、指定できる範囲は 60 秒から run の最大実行時間まで
- 60 秒未満の値は 60 秒に切り上げられ、60 秒を超える値は分単位で切り捨てられる
- タイムアウトするとタスクはキャンセルされる。この処理には 1〜2 分かかることがある
- run とタスクのステータスは failed になり、同じ run 内の他タスク(Starting、Pending、Running)もキャンセルされる。タイムアウト前に完了していたタスクの出力は S3 の出力先にエクスポートされる
- pending 状態で待機していた時間は、タスクの経過時間に算入されない
run 全体の最大実行時間は Workflows - Maximum run duration サービスクォータがあります。既定値は 604,800 秒(7 日)で、調整可能なので必要に応じて引き上げをリクエストできます。
検証環境
| 項目 | 値 |
|---|---|
| リージョン | ap-northeast-1(東京) |
| ワークフローエンジン | WDL(WDL 1.0) |
| コンテナイメージ | ubuntu 24.04(同一リージョンの ECR プライベートリポジトリ、x86_64) |
| ストレージタイプ | DYNAMIC |
| タスクリソース | cpu 2、memory 4 GB |
| omicsTimeout | タイムアウト版は "2m"、ベースラインは未指定 |
S3 出力先、ECR リポジトリ、HealthOmics サービスロールの事前準備は、以下の Nextflow の記事と共通です。ワークフローの言語が変わっても前提リソースの構成自体は変わりません。
WDL ワークフロー定義
今回使用した WDL ワークフロー定義です。SleepTask が sleep 600 を実行するだけの単一タスクのワークフローで、開始時刻と終了時刻を result.txt に書き出します。runtimeセクションではdocker、cpu、memoryに加えてomicsTimeout: "2m"を指定しています。WDL 1.0 ではdocker属性を使います。WDL 1.1 で導入されたcontainer` 属性とは書き方が異なります。
version 1.0
workflow TimeoutDemo {
input {
String container_image
}
call SleepTask {
input:
container_image = container_image
}
output {
File result = SleepTask.result
}
}
task SleepTask {
input {
String container_image
}
command <<<
START=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
sleep 600
echo "$START" > result.txt
date -u +"%Y-%m-%dT%H:%M:%SZ" >> result.txt
>>>
output {
File result = "result.txt"
}
runtime {
docker: container_image
cpu: 2
memory: "4 GB"
omicsTimeout: "2m"
}
}
omicsTimeout指定なし版も実行してベースラインを確認したいので、omicsTiout: "2m"を削ったワークフローもbaseline.wdlとして別途用意しました。
container_image をハードコードせずワークフロー入力として宣言しているので、run 実行時に渡す input.json は次のとおり ECR に保存してあるイメージ名を指定します。
{
"TimeoutDemo.container_image": "<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/<repository-name>:24.04"
}
ワークフローを登録する
baseline.wdl と timeout.wdl をそれぞれ zip 化し、aws omics create-workflow --engine WDL で登録します。
zip -j baseline.zip baseline.wdl
aws omics create-workflow --name healthomics-wdl-timeout-baseline --engine WDL \
--definition-zip fileb://baseline.zip --region ap-northeast-1
レスポンスの id が、この後の start-run で参照するワークフロー ID です。
{
"arn": "arn:aws:omics:ap-northeast-1:<account-id>:workflow/1744239",
"id": "1744239",
"status": "CREATING",
"tags": {},
"uuid": "b8cfe5d3-13b2-ac1a-fec4-655be4b16b89"
}
同様にタイムアウト版も登録します。
zip -j timeout.zip timeout.wdl
aws omics create-workflow --name healthomics-wdl-timeout --engine WDL \
--definition-zip fileb://timeout.zip --region ap-northeast-1
{
"arn": "arn:aws:omics:ap-northeast-1:<account-id>:workflow/7838634",
"id": "7838634",
"status": "CREATING",
"tags": {},
"uuid": "9ccfe5d3-2535-eb92-f43a-a1eb441cb778"
}
create-workflow の直後は status が CREATING です。今回は 8 秒後に両方とも ACTIVE になりました。get-workflow で ACTIVE を確認してから run を開始します。
aws omics get-workflow --id 1744239 --region ap-northeast-1 --query 'status'
"ACTIVE"
検証用ワークフローを実行してみる
それぞれのワークフローに対して start-run を実行します。container_image をワークフロー入力にしているため、--parameters で input.json を渡します。--storage-type は DYNAMIC を明示します。ベースラインとタイムアウト版は独立したワークフローなので、待ち時間を短縮するため並行して起動しました。
aws omics start-run \
--workflow-id 7838634 \
--role-arn arn:aws:iam::<account-id>:role/<service-role-name> \
--output-uri s3://<output-bucket>/wdl-timeout/ \
--parameters file://input.json \
--storage-type DYNAMIC \
--name wdl-timeout-run --region ap-northeast-1
レスポンスの id が run の追跡に使う ID です。
{
"arn": "arn:aws:omics:ap-northeast-1:<account-id>:run/2833398",
"id": "2833398",
"status": "PENDING",
"runOutputUri": "s3://<output-bucket>/wdl-timeout/2833398",
"networkingMode": "RESTRICTED"
}
タイムアウトなし版なら sleep 600 は当然完走する
先にベースラインの結果です。ワークフロー ID 1744239 を同じ形式で起動し、run ID は 9485917 でした。omicsTimeout 設定を削除して同一定義の run はタスクの stopTime から startTime を引くと 616.164 秒で、sleep 600 に対して約 16 秒のオーバーヘッドでした。
aws omics list-run-tasks --id 9485917 --region ap-northeast-1
{
"taskId": "4546924",
"status": "COMPLETED",
"startTime": "2026-08-04T07:25:29.317000+00:00",
"stopTime": "2026-08-04T07:35:45.481000+00:00",
"instanceType": "omics.c.large"
}
タスク内部で記録した result.txt も、開始から正確に 600 秒後の時刻を残していました。
aws s3 cp s3://<output-bucket>/wdl-timeout/9485917/out/result/result.txt -
2026-08-04T07:25:29Z
2026-08-04T07:35:29Z
タイムアウト版は RUNNING から STOPPING を経て FAILED になる
タイムアウト版のステータスを 10 秒間隔でポーリングして見守りました。ステータスの遷移は PENDING から STARTING、RUNNING、STOPPING を経て FAILED でした。
for i in $(seq 1 60); do
date -u +"%Y-%m-%dT%H:%M:%SZ"
aws omics get-run --id 2833398 --region ap-northeast-1 --query 'status' --output text
sleep 10
done
2026-08-04T07:23:52Z STARTING
2026-08-04T07:24:03Z RUNNING
2026-08-04T07:30:51Z STOPPING
2026-08-04T07:33:08Z FAILED
run 単位の statusMessage には、どのタスクが何秒でタイムアウトしたかのメッセージがありました。
aws omics get-run --id 2833398 --region ap-northeast-1 \
--query '{status:status,statusMessage:statusMessage,startTime:startTime,stopTime:stopTime}'
{
"status": "FAILED",
+ "statusMessage": "Task 4352220 timed out after 120 seconds.",
"startTime": "2026-08-04T07:23:51+00:00",
"stopTime": "2026-08-04T07:33:07.369210+00:00"
}
コンソールの実行の概要でも同じ内容を確認できます。ステータスが「エラー」、エラーの理由が TASK_TIMED_OUT、ステータスの説明に run 単位と同じ文言が表示されます。

停止までに指定値より約 60 秒長くかかった
停止までの時間は run 単位でなくタスク単位で確認してみます。run の startTime と stopTime の差には出力のエクスポートなど終了時の共通処理が混ざるためです。list-run-tasks でタスクの startTime と stopTime を確認します。
aws omics list-run-tasks --id 2833398 --region ap-northeast-1
{
"items": [
{
"taskId": "4352220",
"status": "FAILED",
"name": "SleepTask",
"creationTime": "2026-08-04T07:23:56.314407+00:00",
"startTime": "2026-08-04T07:26:09.571000+00:00",
"stopTime": "2026-08-04T07:29:11.845000+00:00",
"instanceType": "omics.c.large"
}
]
}
07:29:11.845 − 07:26:09.571 で 182.274 秒(約 3 分 2 秒)でした。指定した 120 秒に対して停止処理に約 62 秒のオーバーヘッドがあります。公式ドキュメントにも「1〜2 分かかることがある」と書いてあるので想定の範囲内です。
タイムアウトかどうかは CloudWatch Logs では判別できない
list-run-tasks のレスポンスに失敗理由は含まれません。個別タスクの statusMessage と failureReason は get-run-task で取得します。
aws omics get-run-task --id 2833398 --task-id 4352220 --region ap-northeast-1
{
"taskId": "4352220",
"status": "FAILED",
"startTime": "2026-08-04T07:26:09.571000+00:00",
"stopTime": "2026-08-04T07:29:11.845000+00:00",
+ "statusMessage": "Task exceeded the time directive for the process after 120 seconds.",
+ "failureReason": "TASK_TIMED_OUT",
"instanceType": "omics.c.large"
}
failureReason が TASK_TIMED_OUT になり、タイムアウトが原因だと判別できます。この値はマネージメントコンソールの実行の概要にある「エラーの理由」と同じです。なお run 単位とタスク単位で statusMessage の文言は異なりました。タスク単位の「time directive」は、先行して対応した Nextflow の time ディレクティブに由来する表現だと思われ、WDL の omicsTimeout でも共通して使われているように見えました。
一方で CloudWatch Logs には、タイムアウトを示す文言が出ませんでした。タスクログには起動時のトレースだけが残っており、sleep の途中で停止したことはわかりません。
aws logs get-log-events --log-group-name /aws/omics/WorkflowLog \
--log-stream-name "run/2833398/task/4352220" --start-from-head --region ap-northeast-1
Task started
+ echo Task started
+ cd /mnt/workflow/2833398/call-SleepTask/work
+ bash ../command
++ tee -a ../stdout.txt
++ tee -a ../stderr.txt
エンジンログにも Terminated という汎用的なエラーしか出ていませんでした。
aws logs get-log-events --log-group-name /aws/omics/WorkflowLog \
--log-stream-name "run/2833398/engine" --start-from-head --region ap-northeast-1
2026-08-04 07:29:41.186 (TaskPool_0) WARNING ... Failed to run workflow task SleepTask with arn: arn:aws:omics:ap-northeast-1:<account-id>:task/4352220
2026-08-04 07:29:41.188 (TaskPool_0) ERROR ... task SleepTask (timeout.wdl Ln 16 Col 1) failed :: dir: "/mnt/workflow/2833398/call-SleepTask", error: "Terminated"
2026-08-04 07:29:41.246 (MainThread) NOTICE ... aborting workflow
タイムアウトかどうかをログだけで切り分けが難しいことがわかりました。 get-run-task の failureReason を見ましょう。
タイムアウトしたタスクの出力は S3 に残らない
タイムアウトした run の出力先には logs/engine.log だけが残り、result.txt はエクスポートされていませんでした。今回のタスクは sleep 600 の後に result.txt を書く作りなので、停止時点でファイル自体が存在していないので、こちらも想定どおりです。
aws s3 ls s3://<output-bucket>/wdl-timeout/2833398/ --recursive --region ap-northeast-1
2026-08-04 16:23:24 0 wdl-timeout/2833398/
2026-08-04 16:29:44 1372 wdl-timeout/2833398/logs/engine.log
まとめ
AWS HealthOmics の WDL ワークフローで omicsTimeout を設定すると、指定時間を超えたタスクが停止し、run が FAILED になることを確認しました。runtime セクションに 1 行追加するだけで、新規作成中の試行錯誤時などのガードレールとして有用です。
120 秒の指定に対して実際に停止するまでは 182.274 秒で、停止処理に約 62 秒のオーバーヘッドがありました。
タイムアウトが原因かどうかは CloudWatch Logs では判別できず、get-run-task の failureReason を見る必要がありました。目視ならマネージメントコンソールから原因を確認するのが楽でした。
おわりに
Nextflow で先行してサポートされていたタスクレベルタイムアウトが WDL にも来たので試してみました。最近、東京リージョンでの HealthOmics が使えるようになったのでよかったら使ってみてください。









