Netlify Scheduled Functions Debugging Guide 2026
Master scheduled function debugging on Netlify with real error patterns, production code examples, and step-by-step troubleshooting.
TL;DR
Netlify scheduled functions (Functions v2) use cron syntax to trigger serverless code on intervals. Debugging requires combining local testing with netlify functions:invoke, environment variable verification, and proper error handling. Common issues: timezone mismatches, missing schedule configuration, and incomplete IAM permissions. Always test cron expressions before deployment.
---
The Core Challenge
Scheduled functions are deceptively simple until they fail silently in production. Unlike HTTP-triggered functions, you can't curl them locally. Unlike cron jobs on servers you control, you can't SSH in and check logs. This creates a debugging vacuum where functions execute (or don't) in Netlify's infrastructure while you're left guessing why.
Netlify's scheduled functions rely on [AWS EventBridge](https://docs.netlify.com/functions/scheduled-functions/) under the hood. Understanding this is key to debugging effectively.
---
Local Testing Setup
Before deployment, set up proper local testing. Create a test function:
```javascript // netlify/functions/check-health.js export const handler = async (event) => { console.log('Function triggered at:', new Date().toISOString()); console.log('Event:', JSON.stringify(event, null, 2)); try { // Your scheduled logic here const result = await performHealthCheck(); return { statusCode: 200, body: JSON.stringify({ success: true, timestamp: new Date().toISOString(), data: result }) }; } catch (error) { console.error('Health check failed:', error); return { statusCode: 500, body: JSON.stringify({ success: false, error: error.message }) }; } };
export const config = { schedule: '0 */6 * * *' // Every 6 hours };
async function performHealthCheck() { const response = await fetch(process.env.HEALTH_CHECK_URL); return response.json(); } ```
Test locally with:
```bash netlify functions:invoke check-health --local ```
This simulates the execution environment. Verify in your netlify.toml that functions are configured:
```toml [build] command = "npm run build" functions = "netlify/functions"
[dev] functions = "netlify/functions" ```
---
Common Error Messages and Solutions
Error 1: "Task timed out after 900 seconds"
What it means: Your function exceeded Netlify's execution timeout (15 minutes for scheduled functions, verify in [official docs](https://docs.netlify.com/functions/overview/#limits) for current limits).
```javascript // WRONG - Will timeout on large datasets export const handler = async (event) => { const allUsers = await db.query("SELECT * FROM users"); // Process millions of records };
// RIGHT - Use pagination/batching export const handler = async (event) => { const batchSize = 100; const offset = event.queryStringParameters?.offset || 0; const users = await db.query( "SELECT * FROM users LIMIT ? OFFSET ?", [batchSize, offset] ); // Queue next batch if needed if (users.length === batchSize) { await scheduleNextBatch(offset + batchSize); } }; ```
Error 2: "schedule is not a valid cron expression"
What it means: Your cron syntax has errors. Test expressions at [crontab.guru](https://crontab.guru) before deploying.
```javascript // WRONG - Invalid syntax export const config = { schedule: '0 0 * * *' // Missing day-of-week field (5 fields, needs 6 or specific format) };
// RIGHT - Valid cron expressions export const config = { schedule: '0 0 * * *' // Every day at midnight UTC };
// Also valid - 6-field format export const config = { schedule: '0 0 * * * *' // Every second (rarely useful) }; ```
Error 3: "process.env.MY_VARIABLE is undefined"
What it means: Environment variables aren't loaded for scheduled functions. This requires proper setup.
```javascript
// WRONG - Assumes env vars in scheduled context
export const handler = async (event) => {
const apiKey = process.env.SECRET_KEY; // undefined in scheduled context
await fetch('https://api.example.com', {
headers: { 'Authorization': Bearer ${apiKey} }
});
};
// RIGHT - Explicit environment setup
export const handler = async (event) => {
const apiKey = process.env.SECRET_KEY;
if (!apiKey) {
throw new Error('SECRET_KEY not configured in Netlify site settings');
}
await fetch('https://api.example.com', {
headers: { 'Authorization': Bearer ${apiKey} }
});
};
```
Set variables in Netlify UI under Site Settings > Build & Deploy > Environment. Verify via:
```bash netlify env:list ```
---
Production Debugging Workflow
1. Monitor Function Logs
Access logs immediately after deployment:
```bash netlify functions:list netlify logs --function=check-health ```
Or through UI: Functions > Your Function > Logs
2. Check Deployment Status
```bash netlify deploy:list ```
Ensure the current deploy includes your function changes.
3. Verify Cron Execution
Add explicit timestamps to identify if function even runs:
```javascript export const handler = async (event) => { const executionTime = new Date().toISOString(); // Log to external service immediately await fetch(process.env.LOGGING_WEBHOOK, { method: 'POST', body: JSON.stringify({ functionName: 'check-health', executedAt: executionTime, eventSource: event.source }) }); return { statusCode: 200, body: 'Logged' }; }; ```
4. Timezone Verification
Important: Netlify scheduled functions execute in UTC, not your local timezone.
```javascript export const config = { // This runs at 2 AM UTC, not 2 AM your time schedule: '0 2 * * *' };
// Store actual UTC times in logs export const handler = async (event) => { console.log('Executing at UTC:', new Date().toISOString()); console.log('Event source:', event.source); // Should be 'aws.events' }; ```
---
Integration Testing Pattern
Create an integration test that validates scheduled function behavior:
```javascript // test/scheduled-function.test.js const { handler, config } = require('../netlify/functions/check-health');
describe('Scheduled Function', () => { test('executes without errors', async () => { process.env.HEALTH_CHECK_URL = 'https://httpbin.org/status/200'; const response = await handler({ source: 'aws.events', 'detail-type': 'Scheduled Event' }); expect(response.statusCode).toBe(200); }); test('handles missing env vars gracefully', async () => { delete process.env.HEALTH_CHECK_URL; const response = await handler({ source: 'aws.events' }); expect(response.statusCode).toBe(500); expect(JSON.parse(response.body).error).toBeDefined(); }); }); ```
---
Related Resources
---
What am I missing?
Have you debugged Netlify scheduled functions in production? What error messages stumped you? Leave specific examples in the commentsβespecially if you've dealt with:
Accurate, battle-tested examples help the entire community. Please share what the official docs should clarify.