firebase / firebase/firebase-functions

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

Open
#1,734 5 comments 0 reactions 0 assignees View on GitHub
bug needs-author-feedback reproduced
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.