Skip to content

onSchedule() with string parameter creates Cloud Scheduler jobs with incorrect v1 URLs instead of v2 Cloud Run URLs #1734

@ebeloded

Description

@ebeloded

[REQUIRED] Environment info

firebase-functions: 6.4.0
firebase-tools: 14.16.0
Platform: macOS (Darwin 25.0.0)

[REQUIRED] Test case

import { onSchedule } from 'firebase-functions/v2/scheduler'

// This FAILS - creates scheduler with wrong URL format
export const failingScheduler = onSchedule(
  'every 1 minutes',
  async () => {
    console.log('This function gets PERMISSION_DENIED')
  }
)

// This WORKS - creates scheduler with correct URL
export const workingScheduler = onSchedule(
  {
    schedule: 'every 1 minutes', 
    timeZone: 'America/Los_Angeles',
  },
  async () => {
    console.log('This function works correctly')
  }
)

[REQUIRED] Steps to reproduce

  1. Create a v2 scheduled function using the string parameter syntax
  2. Deploy with firebase deploy --only functions
  3. Check Cloud Scheduler console
  4. Observe the scheduler job has URL: https://us-central1-PROJECT.cloudfunctions.net/FUNCTION_NAME (v1 format)
  5. Function execution fails with PERMISSION_DENIED

[REQUIRED] Expected behavior

Both syntaxes should create Cloud Scheduler jobs with the correct v2 Cloud Run URLs (format: https://FUNCTION_NAME-HASH-uc.a.run.app/)

[REQUIRED] Actual behavior

When using the string parameter syntax, Cloud Scheduler jobs are created with v1 function URLs that don't exist, causing PERMISSION_DENIED errors.

Cloud Scheduler shows:

  • Functions with string syntax: URL points to cloudfunctions.net (v1) - FAILS
  • Functions with object syntax: URL points to run.app (v2) - WORKS

Analysis

The TypeScript types allow both signatures:

onSchedule(schedule: string, handler: Function)
onSchedule(options: ScheduleOptions, handler: Function)

However, only the object syntax properly configures the Cloud Scheduler job with the correct Cloud Run URL. This is a critical bug because:

  1. The types suggest both are valid
  2. The deployment succeeds without warnings
  3. The error only appears at runtime when scheduler tries to invoke the function
  4. The error message (PERMISSION_DENIED) doesn't indicate the root cause is a URL mismatch

Workaround

Always use the object syntax with explicit schedule and timeZone properties:

onSchedule({
  schedule: 'every 1 minutes',
  timeZone: 'America/Los_Angeles',
}, handler)

Related Issues

This appears related to:

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions