From bed21070e5844c9984208f034ed0c26ceeca9abd Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 6 May 2026 16:36:58 +0100 Subject: [PATCH 1/8] feat(core): add maxComputeSeconds, deprecate maxDuration in user-facing types --- packages/core/src/v3/config.ts | 14 +++++++++++++- packages/core/src/v3/types/tasks.ts | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/core/src/v3/config.ts b/packages/core/src/v3/config.ts index 40334f04280..efa9c841386 100644 --- a/packages/core/src/v3/config.ts +++ b/packages/core/src/v3/config.ts @@ -165,6 +165,17 @@ export type TriggerConfig = { */ logLevel?: LogLevel; + /** + * The maximum duration in compute-time **seconds** that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. + * + * Minimum value is 5 seconds. + * + * Setting this value will affect all tasks in the project. You can override it on a per-task basis. + * + * @see https://trigger.dev/docs/tasks/overview#maxcomputeseconds-option + */ + maxComputeSeconds?: number; + /** * The maximum duration in compute-time seconds that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. * @@ -172,9 +183,10 @@ export type TriggerConfig = { * * Setting this value will effect all tasks in the project. * + * @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins. * @see https://trigger.dev/docs/tasks/overview#maxduration-option */ - maxDuration: number; + maxDuration?: number; /** * Set a default time-to-live (TTL) for all task runs in the project. If a run is not executed within this time, it will be removed from the queue and never execute. diff --git a/packages/core/src/v3/types/tasks.ts b/packages/core/src/v3/types/tasks.ts index 978a6e5bd0a..4788441ab15 100644 --- a/packages/core/src/v3/types/tasks.ts +++ b/packages/core/src/v3/types/tasks.ts @@ -271,10 +271,19 @@ type CommonTaskOptions< } | MachinePresetName; + /** + * The maximum duration in compute-time **seconds** that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. + * + * Minimum value is 5 seconds. + */ + maxComputeSeconds?: number; + /** * The maximum duration in compute-time seconds that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. * * Minimum value is 5 seconds + * + * @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins. */ maxDuration?: number; @@ -906,12 +915,23 @@ export type TriggerOptions = { */ metadata?: Record; + /** + * The maximum duration in compute-time **seconds** that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. + * + * This will override the task's `maxComputeSeconds` (or the legacy `maxDuration`). + * + * Minimum value is 5 seconds. + */ + maxComputeSeconds?: number; + /** * The maximum duration in compute-time seconds that a task run is allowed to run. If the task run exceeds this duration, it will be stopped. * * This will override the task's maxDuration. * * Minimum value is 5 seconds + * + * @deprecated Use `maxComputeSeconds` instead — same semantics, clearer unit. If both are set, `maxComputeSeconds` wins. */ maxDuration?: number; From 9206b98a632a0575e533ab3abaf47c70dc142a11 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 6 May 2026 16:38:08 +0100 Subject: [PATCH 2/8] feat(sdk): resolve maxComputeSeconds at user-facing boundaries - defineConfig: resolves maxComputeSeconds ?? maxDuration into maxDuration - new resolveMaxComputeSeconds helper for shared.ts - task definitions, trigger and batchTrigger options funnel through helper Internal references to maxDuration (run engine, queues, DB) are unchanged. --- packages/trigger-sdk/src/v3/config.ts | 10 +++- .../trigger-sdk/src/v3/maxComputeSeconds.ts | 13 +++++ packages/trigger-sdk/src/v3/shared.ts | 53 ++++++++++++------- 3 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 packages/trigger-sdk/src/v3/maxComputeSeconds.ts diff --git a/packages/trigger-sdk/src/v3/config.ts b/packages/trigger-sdk/src/v3/config.ts index 3bf32ac6670..39d62985628 100644 --- a/packages/trigger-sdk/src/v3/config.ts +++ b/packages/trigger-sdk/src/v3/config.ts @@ -9,7 +9,15 @@ export type { } from "@trigger.dev/core/v3"; export function defineConfig(config: TriggerConfig): TriggerConfig { - return config; + // `maxComputeSeconds` is the new name for `maxDuration`. If both are set, the new + // name wins. Internally the SDK and platform still read `maxDuration`, so we + // collapse the two fields here at the user-facing boundary. + const { maxComputeSeconds, maxDuration, ...rest } = config; + const resolved = maxComputeSeconds ?? maxDuration; + return { + ...rest, + ...(resolved !== undefined ? { maxDuration: resolved } : {}), + }; } export type { TriggerConfig }; diff --git a/packages/trigger-sdk/src/v3/maxComputeSeconds.ts b/packages/trigger-sdk/src/v3/maxComputeSeconds.ts new file mode 100644 index 00000000000..d2045d4eeb3 --- /dev/null +++ b/packages/trigger-sdk/src/v3/maxComputeSeconds.ts @@ -0,0 +1,13 @@ +/** + * Collapse the user-facing `maxComputeSeconds` (new name) and `maxDuration` (deprecated) + * into a single value. If both are provided, `maxComputeSeconds` wins. + * + * Internal SDK/CLI/platform code only reads `maxDuration`, so all call sites that + * accept user input should funnel through this helper before forwarding the value. + */ +export function resolveMaxComputeSeconds(input: { + maxComputeSeconds?: number; + maxDuration?: number; +}): number | undefined { + return input.maxComputeSeconds ?? input.maxDuration; +} diff --git a/packages/trigger-sdk/src/v3/shared.ts b/packages/trigger-sdk/src/v3/shared.ts index b8e1874b5be..d44f96d6a42 100644 --- a/packages/trigger-sdk/src/v3/shared.ts +++ b/packages/trigger-sdk/src/v3/shared.ts @@ -31,6 +31,7 @@ import { TaskRunExecutionResult, TaskRunPromise, } from "@trigger.dev/core/v3"; +import { resolveMaxComputeSeconds } from "./maxComputeSeconds.js"; import { tracer } from "./tracer.js"; import type { @@ -258,7 +259,7 @@ export function createTask< machine: typeof params.machine === "string" ? { preset: params.machine } : params.machine, triggerSource: params.triggerSource, agentConfig: params.agentConfig, - maxDuration: params.maxDuration, + maxDuration: resolveMaxComputeSeconds(params), ttl: params.ttl, payloadSchema: params.jsonSchema, fns: { @@ -412,7 +413,7 @@ export function createSchemaTask< machine: typeof params.machine === "string" ? { preset: params.machine } : params.machine, triggerSource: params.triggerSource, agentConfig: params.agentConfig, - maxDuration: params.maxDuration, + maxDuration: resolveMaxComputeSeconds(params), ttl: params.ttl, fns: { run: params.run, @@ -733,7 +734,7 @@ export async function batchTriggerById( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -990,7 +991,7 @@ export async function batchTriggerByIdAndWait( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -1028,7 +1029,10 @@ export async function batchTriggerByIdAndWait( ctx, }); - const runs = await handleBatchTaskRunExecutionResultV2(result.items, response.taskIdentifiers); + const runs = await handleBatchTaskRunExecutionResultV2( + result.items, + response.taskIdentifiers + ); return { id: result.id, @@ -1072,7 +1076,10 @@ export async function batchTriggerByIdAndWait( ctx, }); - const runs = await handleBatchTaskRunExecutionResultV2(result.items, response.taskIdentifiers); + const runs = await handleBatchTaskRunExecutionResultV2( + result.items, + response.taskIdentifiers + ); return { id: result.id, @@ -1249,7 +1256,7 @@ export async function batchTriggerTasks( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -1511,7 +1518,7 @@ export async function batchTriggerAndWaitTasks( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -1966,7 +1979,7 @@ async function* transformBatchItemsStreamForWait( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -2016,7 +2029,7 @@ async function* transformBatchByTaskItemsStream( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: (await makeIdempotencyKey(item.options?.idempotencyKey)) ?? batchItemIdempotencyKey, idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, @@ -2181,7 +2194,7 @@ async function* transformSingleTaskBatchItemsStreamForWait( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: finalIdempotencyKey?.toString(), idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, idempotencyKeyOptions, @@ -2231,7 +2244,7 @@ async function trigger_internal( tags: options?.tags, maxAttempts: options?.maxAttempts, metadata: options?.metadata, - maxDuration: options?.maxDuration, + maxDuration: options ? resolveMaxComputeSeconds(options) : undefined, parentRunId: taskContext.ctx?.run.id, machine: options?.machine, priority: options?.priority, @@ -2315,7 +2328,7 @@ async function batchTrigger_internal( tags: item.options?.tags, maxAttempts: item.options?.maxAttempts, metadata: item.options?.metadata, - maxDuration: item.options?.maxDuration, + maxDuration: item.options ? resolveMaxComputeSeconds(item.options) : undefined, idempotencyKey: finalIdempotencyKey?.toString(), idempotencyKeyTTL: item.options?.idempotencyKeyTTL ?? options?.idempotencyKeyTTL, idempotencyKeyOptions, @@ -2488,7 +2501,7 @@ async function triggerAndWait_internal Date: Wed, 6 May 2026 16:38:43 +0100 Subject: [PATCH 3/8] test(sdk): cover maxComputeSeconds precedence in defineConfig and helper --- packages/trigger-sdk/src/v3/config.test.ts | 29 +++++++++++++++++++ .../src/v3/maxComputeSeconds.test.ts | 20 +++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 packages/trigger-sdk/src/v3/config.test.ts create mode 100644 packages/trigger-sdk/src/v3/maxComputeSeconds.test.ts diff --git a/packages/trigger-sdk/src/v3/config.test.ts b/packages/trigger-sdk/src/v3/config.test.ts new file mode 100644 index 00000000000..fb2b4289d8c --- /dev/null +++ b/packages/trigger-sdk/src/v3/config.test.ts @@ -0,0 +1,29 @@ +import { describe, it, expect } from "vitest"; +import { defineConfig } from "./config.js"; + +describe("defineConfig - maxComputeSeconds", () => { + it("uses maxComputeSeconds when only maxComputeSeconds is set", () => { + const cfg = defineConfig({ project: "p", maxComputeSeconds: 600 }); + expect(cfg.maxDuration).toBe(600); + }); + + it("uses maxDuration when only maxDuration is set", () => { + const cfg = defineConfig({ project: "p", maxDuration: 600 }); + expect(cfg.maxDuration).toBe(600); + }); + + it("prefers maxComputeSeconds when both are set", () => { + const cfg = defineConfig({ project: "p", maxComputeSeconds: 600, maxDuration: 9999 }); + expect(cfg.maxDuration).toBe(600); + }); + + it("leaves maxDuration unset when neither is provided", () => { + const cfg = defineConfig({ project: "p" }); + expect(cfg.maxDuration).toBeUndefined(); + }); + + it("strips maxComputeSeconds from the returned config", () => { + const cfg = defineConfig({ project: "p", maxComputeSeconds: 600 }); + expect((cfg as { maxComputeSeconds?: number }).maxComputeSeconds).toBeUndefined(); + }); +}); diff --git a/packages/trigger-sdk/src/v3/maxComputeSeconds.test.ts b/packages/trigger-sdk/src/v3/maxComputeSeconds.test.ts new file mode 100644 index 00000000000..6898a16610a --- /dev/null +++ b/packages/trigger-sdk/src/v3/maxComputeSeconds.test.ts @@ -0,0 +1,20 @@ +import { describe, it, expect } from "vitest"; +import { resolveMaxComputeSeconds } from "./maxComputeSeconds.js"; + +describe("resolveMaxComputeSeconds", () => { + it("returns maxComputeSeconds when only maxComputeSeconds is set", () => { + expect(resolveMaxComputeSeconds({ maxComputeSeconds: 300 })).toBe(300); + }); + + it("returns maxDuration when only maxDuration is set", () => { + expect(resolveMaxComputeSeconds({ maxDuration: 300 })).toBe(300); + }); + + it("prefers maxComputeSeconds when both are set", () => { + expect(resolveMaxComputeSeconds({ maxComputeSeconds: 300, maxDuration: 999 })).toBe(300); + }); + + it("returns undefined when neither is set", () => { + expect(resolveMaxComputeSeconds({})).toBeUndefined(); + }); +}); From 73c9a40e2f9c09b97e436863bcf0cf2b486431a0 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 6 May 2026 16:39:31 +0100 Subject: [PATCH 4/8] feat(cli): use maxComputeSeconds in init templates --- packages/cli-v3/templates/examples/schedule.mjs.template | 4 ++-- packages/cli-v3/templates/examples/schedule.ts.template | 4 ++-- packages/cli-v3/templates/examples/simple.mjs.template | 4 ++-- packages/cli-v3/templates/examples/simple.ts.template | 4 ++-- packages/cli-v3/templates/trigger.config.mjs.template | 4 ++-- packages/cli-v3/templates/trigger.config.ts.template | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/cli-v3/templates/examples/schedule.mjs.template b/packages/cli-v3/templates/examples/schedule.mjs.template index 5622b37a91e..56b7fafd74d 100644 --- a/packages/cli-v3/templates/examples/schedule.mjs.template +++ b/packages/cli-v3/templates/examples/schedule.mjs.template @@ -4,8 +4,8 @@ export const firstScheduledTask = schedules.task({ id: "first-scheduled-task", // Every hour cron: "0 * * * *", - // Set an optional maxDuration to prevent tasks from running indefinitely - maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute + // Set an optional maxComputeSeconds to prevent tasks from running indefinitely + maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute run: async (payload, { ctx }) => { // The payload contains the last run timestamp that you can use to check if this is the first run // And calculate the time since the last run diff --git a/packages/cli-v3/templates/examples/schedule.ts.template b/packages/cli-v3/templates/examples/schedule.ts.template index 5622b37a91e..56b7fafd74d 100644 --- a/packages/cli-v3/templates/examples/schedule.ts.template +++ b/packages/cli-v3/templates/examples/schedule.ts.template @@ -4,8 +4,8 @@ export const firstScheduledTask = schedules.task({ id: "first-scheduled-task", // Every hour cron: "0 * * * *", - // Set an optional maxDuration to prevent tasks from running indefinitely - maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute + // Set an optional maxComputeSeconds to prevent tasks from running indefinitely + maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute run: async (payload, { ctx }) => { // The payload contains the last run timestamp that you can use to check if this is the first run // And calculate the time since the last run diff --git a/packages/cli-v3/templates/examples/simple.mjs.template b/packages/cli-v3/templates/examples/simple.mjs.template index 8b1bf12d4f1..054bc2e7cd5 100644 --- a/packages/cli-v3/templates/examples/simple.mjs.template +++ b/packages/cli-v3/templates/examples/simple.mjs.template @@ -2,8 +2,8 @@ import { logger, task, wait } from "@trigger.dev/sdk/v3"; export const helloWorldTask = task({ id: "hello-world", - // Set an optional maxDuration to prevent tasks from running indefinitely - maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute + // Set an optional maxComputeSeconds to prevent tasks from running indefinitely + maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute run: async (payload, { ctx }) => { logger.log("Hello, world!", { payload, ctx }); diff --git a/packages/cli-v3/templates/examples/simple.ts.template b/packages/cli-v3/templates/examples/simple.ts.template index 9ef3d529f3a..83ae9280412 100644 --- a/packages/cli-v3/templates/examples/simple.ts.template +++ b/packages/cli-v3/templates/examples/simple.ts.template @@ -2,8 +2,8 @@ import { logger, task, wait } from "@trigger.dev/sdk/v3"; export const helloWorldTask = task({ id: "hello-world", - // Set an optional maxDuration to prevent tasks from running indefinitely - maxDuration: 300, // Stop executing after 300 secs (5 mins) of compute + // Set an optional maxComputeSeconds to prevent tasks from running indefinitely + maxComputeSeconds: 300, // Stop executing after 300 secs (5 mins) of compute run: async (payload: any, { ctx }) => { logger.log("Hello, world!", { payload, ctx }); diff --git a/packages/cli-v3/templates/trigger.config.mjs.template b/packages/cli-v3/templates/trigger.config.mjs.template index d50033647e2..5b1e857d341 100644 --- a/packages/cli-v3/templates/trigger.config.mjs.template +++ b/packages/cli-v3/templates/trigger.config.mjs.template @@ -4,10 +4,10 @@ export default defineConfig({ project: "${projectRef}", runtime: "${runtime}", logLevel: "log", - // The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped. + // The max compute seconds a task is allowed to run. If the run exceeds this, it will be stopped. // You can override this on an individual task. // See https://trigger.dev/docs/runs/max-duration - maxDuration: 3600, + maxComputeSeconds: 3600, retries: { enabledInDev: true, default: { diff --git a/packages/cli-v3/templates/trigger.config.ts.template b/packages/cli-v3/templates/trigger.config.ts.template index d50033647e2..5b1e857d341 100644 --- a/packages/cli-v3/templates/trigger.config.ts.template +++ b/packages/cli-v3/templates/trigger.config.ts.template @@ -4,10 +4,10 @@ export default defineConfig({ project: "${projectRef}", runtime: "${runtime}", logLevel: "log", - // The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped. + // The max compute seconds a task is allowed to run. If the run exceeds this, it will be stopped. // You can override this on an individual task. // See https://trigger.dev/docs/runs/max-duration - maxDuration: 3600, + maxComputeSeconds: 3600, retries: { enabledInDev: true, default: { From 785460f6cdd92e094f33ed99e46ac434402dcdb2 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 6 May 2026 16:39:49 +0100 Subject: [PATCH 5/8] chore: changeset for maxComputeSeconds --- .changeset/max-compute-seconds.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/max-compute-seconds.md diff --git a/.changeset/max-compute-seconds.md b/.changeset/max-compute-seconds.md new file mode 100644 index 00000000000..56cac672521 --- /dev/null +++ b/.changeset/max-compute-seconds.md @@ -0,0 +1,7 @@ +--- +"@trigger.dev/core": patch +"@trigger.dev/sdk": patch +"trigger.dev": patch +--- + +Add `maxComputeSeconds` as the user-facing replacement for `maxDuration` on `defineConfig`, task definitions, and trigger options. The new name makes the unit (compute-time seconds) unambiguous at the call site. `maxDuration` is JSDoc-deprecated and still accepted; if both are set, `maxComputeSeconds` wins. The `init` templates have been updated to use the new name. From 2588556b442677d8d2117c00b0cccb55a779acaf Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Wed, 6 May 2026 21:38:56 +0100 Subject: [PATCH 6/8] chore(references): use maxComputeSeconds in hello-world for manual testing - trigger.config.ts: top-level maxComputeSeconds - example.ts: per-task maxComputeSeconds on maxDurationTask - example.ts: per-trigger override on triggerAndWait Variable name maxDurationTask kept since it labels the legacy fixture concept; the payload.maxDuration field is unrelated to the SDK property and untouched. --- references/hello-world/src/trigger/example.ts | 4 ++-- references/hello-world/trigger.config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/references/hello-world/src/trigger/example.ts b/references/hello-world/src/trigger/example.ts index a3070d56339..718a2c77ca1 100644 --- a/references/hello-world/src/trigger/example.ts +++ b/references/hello-world/src/trigger/example.ts @@ -139,7 +139,7 @@ export const maxDurationTask = task({ maxTimeoutInMs: 2_000, factor: 1.4, }, - maxDuration: 5, + maxComputeSeconds: 5, run: async (payload: { sleepFor: number }, { signal, ctx }) => { await setTimeout(payload.sleepFor * 1000, { signal }); }, @@ -150,7 +150,7 @@ export const maxDurationParentTask = task({ run: async (payload: { sleepFor?: number; maxDuration?: number }, { ctx, signal }) => { const result = await maxDurationTask.triggerAndWait( { sleepFor: payload.sleepFor ?? 10 }, - { maxDuration: timeout.None } + { maxComputeSeconds: timeout.None } ); return result; diff --git a/references/hello-world/trigger.config.ts b/references/hello-world/trigger.config.ts index e0b875cd6d1..86de9f25a05 100644 --- a/references/hello-world/trigger.config.ts +++ b/references/hello-world/trigger.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ maxExecutionsPerProcess: 20, }, logLevel: "debug", - maxDuration: 3600, + maxComputeSeconds: 3600, ttl: "1h", retries: { enabledInDev: true, From 11fc7a22974806a3e674590802553e48be302980 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Fri, 8 May 2026 09:45:56 +0100 Subject: [PATCH 7/8] Updated the error and link to the docs --- packages/core/src/v3/errors.ts | 10 +++++++++- packages/core/src/v3/links.ts | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/core/src/v3/errors.ts b/packages/core/src/v3/errors.ts index d32e32f91c9..704d426a02b 100644 --- a/packages/core/src/v3/errors.ts +++ b/packages/core/src/v3/errors.ts @@ -656,7 +656,9 @@ export class MaxDurationExceededError extends Error { public readonly maxDurationInSeconds: number, public readonly elapsedTimeInSeconds: number ) { - super(`Run exceeded maximum compute time (maxDuration) of ${maxDurationInSeconds} seconds`); + super( + `Run exceeded maximum compute time (maxComputeSeconds) of ${maxDurationInSeconds} seconds` + ); this.name = "MaxDurationExceededError"; } @@ -756,6 +758,12 @@ const prettyInternalErrors: Partial< href: links.docs.troubleshooting.uncaughtException, }, }, + MAX_DURATION_EXCEEDED: { + link: { + name: "How to set maxComputeSeconds (maxDuration)", + href: links.docs.maxDuration, + }, + }, }; const getPrettyTaskRunError = (code: TaskRunInternalError["code"]): TaskRunInternalError => { diff --git a/packages/core/src/v3/links.ts b/packages/core/src/v3/links.ts index 739f9dd28f7..0ce1e08d44a 100644 --- a/packages/core/src/v3/links.ts +++ b/packages/core/src/v3/links.ts @@ -26,6 +26,7 @@ export const links = { personalAccessToken: "https://trigger.dev/docs/github-actions#creating-a-personal-access-token", }, + maxDuration: "https://trigger.dev/docs/runs/max-duration", }, site: { home: "https://trigger.dev", From e785924d5d322e7a5e686bf3f9dfef15566051da Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Fri, 8 May 2026 18:42:18 +0100 Subject: [PATCH 8/8] fix(cli): resolve maxComputeSeconds in validateConfig for bypass cases If a user exports a trigger.config plain object without going through defineConfig() (TypeScript allows it), validation previously rejected the new maxComputeSeconds field with an error mentioning maxDuration. Mirror the SDK boundary's resolution at the CLI boundary so downstream internals (which still read maxDuration) keep working. --- packages/cli-v3/src/config.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/cli-v3/src/config.ts b/packages/cli-v3/src/config.ts index af5623e0176..e5e139859ca 100644 --- a/packages/cli-v3/src/config.ts +++ b/packages/cli-v3/src/config.ts @@ -341,11 +341,16 @@ function validateConfig(config: TriggerConfig, warn = true) { config.build.extensions.push(adaptResolveEnvVarsToSyncEnvVarsExtension(resolveEnvVarsFn)); } - if (!config.maxDuration) { + // Resolve maxComputeSeconds → maxDuration so plain-object exports that bypass + // defineConfig() still work. This mirrors the resolution defineConfig() applies + // at the SDK boundary; downstream CLI/runtime code only reads `maxDuration`. + const resolvedMaxDuration = config.maxComputeSeconds ?? config.maxDuration; + if (!resolvedMaxDuration) { throw new Error( - `The "maxDuration" trigger.config option is now required, and must be at least 5 seconds.` + `The "maxComputeSeconds" trigger.config option is now required, and must be at least 5 seconds.` ); } + config.maxDuration = resolvedMaxDuration; if (config.runtime && config.runtime === "bun") { warn &&