anomalyco/sst · error · VisibleError

You cannot provide both a function and a task in the "${name

Error message

You cannot provide both a function and a task in the "${name}" CronV2 component.

What it means

CronV2 requires exactly one schedule target: either a Lambda `function` or an ECS `task`. This error is thrown in normalizeTargets when both a function/job and a `task` are provided, since EventBridge Scheduler can only have one unambiguous target per schedule.

Source

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

    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.`,
        );
    }

    function createFunction() {
      if (!fnArgs) return;

      return fnArgs.apply((fnArgs) =>
        functionBuilder(`${name}Handler`, fnArgs, {}, undefined, {
          parent,
        }),
      );
    }

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Delete the `function` (or `job`) property if the cron should run the ECS task
  2. Delete the `task` property if the cron should invoke the Lambda function
  3. Split into two separate CronV2 components if you genuinely need both targets

Example fix

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

Strategy: validation

Validate before calling

function validateCronV2Target(args: sst.aws.CronV2Args) {
  const hasFn = !!(args.function || args.job);
  if (hasFn && args.task) throw new Error("Provide either a function or a task, not both");
}

Type guard

function hasSingleTarget(args: { function?: unknown; job?: unknown; task?: unknown }): boolean {
  const fn = Boolean(args.function ?? args.job);
  const task = Boolean(args.task);
  return fn !== task;
}

Try / catch

try {
  new sst.aws.CronV2("MyCron", args);
} catch (e) {
  if (e instanceof Error && e.message.includes("both a function and a task")) {
    console.error("Delete either the function or the task property");
  } else throw e;
}

Prevention

When it happens

Trigger: `new sst.aws.CronV2(name, { schedule, task, function })` or `new sst.aws.CronV2(name, { schedule, task, job })` — both `fnArgs` and `args.task` truthy.

Common situations: Refactoring a cron that used to run a function into one that runs an ECS task without deleting the `function` key; combining two cron examples; a shared config merging function- and task-based crons.

Related errors


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