anomalyco/sst · error · VisibleError

You cannot provide both "job" and "function" in the "${name}

Error message

You cannot provide both "job" and "function" in the "${name}" CronV2 component. The "job" property has been deprecated. Use "function" instead.

What it means

SST's CronV2 component accepts a scheduled target either via the newer `function` property or the deprecated `job` property. The component throws this VisibleError during argument normalization when both are supplied, because it cannot unambiguously decide which target to schedule. It tells you to migrate to the single `function` property.

Source

Thrown at platform/src/components/aws/cron-v2.ts:326

    const parent = this;

    const fnArgs = normalizeFunction();
    const event = output(args.event || {});
    normalizeTargets();
    const enabled = output(args.enabled ?? true);
    const fn = createFunction();
    const role = createRole();
    const schedule = createSchedule();

    this._name = name;
    this.fn = fn;
    this._role = role;
    this._schedule = schedule;

    function normalizeFunction() {
      if (args.job && args.function)
        throw new VisibleError(
          `You cannot provide both "job" and "function" in the "${name}" CronV2 component. The "job" property has been deprecated. Use "function" instead.`,
        );

      const input = args.function ?? args.job;
      return input ? output(input) : undefined;
    }

    function normalizeTargets() {
      if (fnArgs && args.task)
        throw new VisibleError(
          `You cannot provide both a function and a task in the "${name}" CronV2 component.`,
        );
      if (!fnArgs && !args.task)
        throw new VisibleError(
          `You must provide either a function or a task in the "${name}" CronV2 component.`,
        );
    }

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Remove the deprecated `job` property and keep only `function`
  2. If `job` held an object like { function, ... }, move any nested fields into `function` and delete `job`
  3. Search your sst.config.ts for `job:` in CronV2 args to catch remaining duplicates

Example fix

// before
new sst.aws.CronV2("MyCron", {
  schedule: "rate(1 day)",
  job: { function: handler },
  function: handler,
});
// after
new sst.aws.CronV2("MyCron", {
  schedule: "rate(1 day)",
  function: handler,
});
Defensive patterns

Strategy: validation

Validate before calling

function validateCronV2Args(args: sst.aws.CronV2Args) {
  if (args.job && args.function)
    throw new Error("Set only one of 'job' (deprecated) or 'function', not both");
}

Type guard

function hasNoPropConflict<K extends string>(a: Record<string, unknown>, keys: [K, K]): boolean {
  return !(a[keys[0]] && a[keys[1]]);
}

Try / catch

try {
  new sst.aws.CronV2("MyCron", args);
} catch (e) {
  if (e instanceof Error && e.message.includes('both "job" and "function"')) {
    console.error("Remove the deprecated 'job' property; use 'function' only");
  } else throw e;
}

Prevention

When it happens

Trigger: Creating `new sst.aws.CronV2(name, {...})` with both `args.function` and `args.job` set (e.g. after partially migrating config from the deprecated `job` API and leaving the old key in place).

Common situations: Migrating an sst.config.ts from an older SST version where `job` was the accepted key; copy-pasting an example that uses `job` while an IDE auto-completion added `function`; a stale `job` entry kept alongside a newly added `function`.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/7a6ead11b3b77769. Report an issue: GitHub.