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}" Cron component. The "job" property has been deprecated. Use "function" instead.

What it means

SST's Cron component (v1) accepts the scheduled function via `function` or the deprecated `job` property. This VisibleError is thrown in normalizeFunction when both are provided, since the component cannot decide which one to use. The message directs you to the `function` property.

Source

Thrown at platform/src/components/aws/cron.ts:261

    const parent = this;

    const fnArgs = normalizeFunction();
    const event = output(args.event || {});
    normalizeTargets();
    const enabled = output(args.enabled ?? true);
    const rule = createRule();
    const fn = createFunction();
    const role = createRole();
    const target = createTarget();

    this.name = name;
    this.fn = fn;
    this.rule = rule;
    this.target = target;

    function normalizeFunction() {
      if (args.job && args.function)
        throw new VisibleError(
          `You cannot provide both "job" and "function" in the "${name}" Cron 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}" Cron component.`,
        );
    }

    function createRule() {
      return new cloudwatch.EventRule(
        ...transform(
          args.transform?.rule,

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Remove the deprecated `job` property and keep `function`
  2. Move any nested configuration from `job` into `function` and delete `job`
  3. Grep the config for `job:` inside Cron args to catch all occurrences

Example fix

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

Strategy: validation

Validate before calling

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

Type guard

function hasNoPropConflict(a: Record<string, unknown>, k1: string, k2: string): boolean {
  return !(a[k1] && a[k2]);
}

Try / catch

try {
  new sst.aws.Cron("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: `new sst.aws.Cron(name, {...})` with both `args.function` and `args.job` set — typically after a partial migration from `job` to `function`.

Common situations: Upgrading sst.config.ts from the old `job` API and leaving the old key; copy-paste of older examples combined with modern autocomplete; a template with both keys present.

Related errors


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