firebase / firebase/firebase-functions
onSchedule() with string parameter creates Cloud Scheduler jobs with incorrect v1 URLs instead of v2 Cloud Run URLs
- Dominant language
- TypeScript
- Stars
- 1.1k
- Forks
- 232
- Avg merge
- 20h 46m
- Merged PRs (30d)
- 15
Description
### [REQUIRED] Environment info
**firebase-functions:** 6.4.0
**firebase-tools:** 14.16.0
**Platform:** macOS (Darwin 25.0.0)
### [REQUIRED] Test case
```typescript
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:
```typescript
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:
```typescript
onSchedule({
schedule: 'every 1 minutes',
timeZone: 'America/Los_Angeles',
}, handler)
```
### Related Issues
This appears related to:
- #1425 (PERMISSION_DENIED errors)
- #1447 (Cloud Function V2 not creating deterministic Function URL)
- #1293 (V2 scheduled functions deployment issues)
Contributor guide
Research direction
Start at the TypeScript onSchedule(string, handler) entry point and compare it with the object overload. Deploy both forms with firebase deploy --only functions, then verify that the string form creates the same v2 Cloud Run URL as the object form and no longer causes PERMISSION_DENIED in Cloud Scheduler.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- gcp, typescript
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100