mastra-ai/mastra · error

terminationGraceMs must be greater than zero.

Error message

terminationGraceMs must be greater than zero.

What it means

attachWorkerDeployment validates terminationGraceMs when provided: it must be a finite number greater than zero, since it is used as the SIGTERM-to-SIGKILL grace period when stopping the worker. Invalid values are rejected before any sandbox work starts.

Source

Thrown at deployers/sandbox/src/worker.ts:147

    throw workerPhaseError('install', error);
  }

  return createExecution(config, executionId, options.input);
}

/** Reattach to a persisted worker execution without its original launch configuration. */
export async function attachWorkerDeployment(options: AttachWorkerDeploymentOptions): Promise<SandboxWorkerExecution> {
  if (!options.sandbox.executeCommand) {
    throw new Error(
      `Sandbox provider "${options.sandbox.provider}" does not support executeCommand, which is required for worker deploys.`,
    );
  }
  validateExecutionId(options.executionId);
  if (
    options.terminationGraceMs !== undefined &&
    (!Number.isFinite(options.terminationGraceMs) || options.terminationGraceMs <= 0)
  ) {
    throw new Error('terminationGraceMs must be greater than zero.');
  }

  let remoteDir: string | undefined;
  const config: WorkerExecutionConfig = {
    sandbox: options.sandbox,
    resolveRemoteDir: async () => (remoteDir ??= await resolveRemoteDir(options.sandbox, options.remoteDir)),
    terminationGraceMs: options.terminationGraceMs ?? 5_000,
  };
  const info = await getInfoSafe(options.sandbox);
  return execution(config, options.executionId, info?.id ?? options.sandbox.id, info?.timeoutAt);
}

function validateOptions(options: DeployWorkerToSandboxOptions): void {
  if (!options.sandbox.executeCommand) {
    throw new Error(
      `Sandbox provider "${options.sandbox.provider}" does not support executeCommand, which is required for worker deploys.`,
    );
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass a positive finite number of milliseconds (e.g. 5000 for 5s).
  2. If the option is unset upstream, omit it entirely (undefined is allowed) rather than passing 0.
  3. Check the parsing path — wrap Number() conversions and validate with Number.isFinite.

Example fix

// before
await attachWorkerDeployment({ sandbox, executionId, terminationGraceMs: 0 });
// after
await attachWorkerDeployment({ sandbox, executionId, terminationGraceMs: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

if (opts.terminationGraceMs !== undefined && (!Number.isFinite(opts.terminationGraceMs) || opts.terminationGraceMs <= 0)) throw new Error('terminationGraceMs must be a positive finite number');

Type guard

const isValidGraceMs = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && v > 0;

Prevention

When it happens

Trigger: Passing terminationGraceMs of 0, a negative number, NaN, or Infinity to attachWorkerDeployment.

Common situations: Copy-pasted config with grace period left at 0; parsing env vars/JSON strings without numeric coercion producing NaN; unit confusion (seconds entered where milliseconds expected resulting in tiny/zero values after conversion).

Understand the failure class

Background: Invalid option value errors: "must be one of", "is not a valid", and "only allows" failures explained — this error's family across 23 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1983437820aecf89. Report an issue: GitHub.