Troubleshooting Guide

This guide helps you solve common CronJS issues and provides solutions for frequent problems.

Common Error Messages

1. Syntax Errors in JavaScript Code

Error Message: SyntaxError: Unexpected token

Causes:

  • Missing semicolons or brackets
  • Invalid JavaScript syntax
  • Typos in code

Solutions:

// ❌ Common syntax errors
console.log('Hello World'  // Missing closing parenthesis
const data = await fetch()  // Missing semicolon

// ✅ Correct syntax
console.log('Hello World');
const data = await fetch('https://api.example.com');

Prevention:

  • Use the code editor’s syntax highlighting
  • Test code in small pieces
  • Use browser developer tools to validate syntax

2. Timeout Errors

Error Message: Job execution timed out after 60 seconds

Causes:

  • Job takes longer than 60-second limit
  • Infinite loops or hanging operations
  • Slow API responses

Solutions:

// ✅ Add timeout to fetch requests
const controller = new AbortController();
setTimeout(() => controller.abort(), 50000); // 50 seconds

try {
  const response = await fetch(apiUrl, {
    signal: controller.signal,
  });
} catch (error) {
  if (error.name === "AbortError") {
    console.error("Request timed out");
  }
  throw error;
}

// ✅ Process data in smaller chunks
async function processInBatches(items, batchSize = 10) {
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    await processBatch(batch);
    console.log(`Processed ${i + batch.length}/${items.length} items`);
  }
}

Prevention:

  • Keep jobs under 50 seconds for safety margin
  • Use progress logging to track execution
  • Consider upgrading to paid plans for higher timeout limits

3. Dependency Installation Failures

Error Message: npm install failed: Package not found

Causes:

  • Misspelled package names
  • Private packages not accessible
  • Package doesn’t exist on npm

Solutions:

// ✅ Verify package names on npmjs.com
// Common correct package names:
const axios = require("axios"); // Not 'axios-http'
const _ = require("lodash"); // Not 'lodash-utils'
const moment = require("moment"); // Not 'momentjs'

// ✅ Use specific versions if needed
// In dependencies section: [email protected]

Prevention:

  • Double-check package names on npmjs.com
  • Use exact package names from npm documentation
  • Test dependencies in local environment first

4. Authentication Token Expiration

Error Message: Authentication failed: Token expired

Causes:

  • Firebase token expired during long-running job
  • Network connectivity issues

Solutions:

// ✅ Handle authentication errors gracefully
try {
  const response = await fetch(apiUrl, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  if (response.status === 401) {
    console.error("Authentication failed - token may be expired");
    throw new Error("Authentication failed");
  }
} catch (error) {
  console.error("Request failed:", error.message);
  throw error;
}

Prevention:

  • Keep job execution under timeout limits
  • Handle 401 responses gracefully
  • Log out and log back in if issues persist

5. Resource Limit Exceeded

Error Message: Job killed: Memory limit exceeded

Causes:

  • Processing large datasets in memory
  • Memory leaks in code
  • Exceeding 128MB memory limit

Solutions:

// ✅ Process data in streams or chunks
async function processLargeFile(data) {
  const chunkSize = 1000;

  for (let i = 0; i < data.length; i += chunkSize) {
    const chunk = data.slice(i, i + chunkSize);

    // Process chunk
    await processChunk(chunk);

    // Clear references to help garbage collection
    chunk.length = 0;

    // Log memory usage
    const usage = process.memoryUsage();
    console.log(`Memory: ${Math.round(usage.heapUsed / 1024 / 1024)}MB`);
  }
}

// ✅ Monitor memory usage
function checkMemoryUsage() {
  const usage = process.memoryUsage();
  const heapUsedMB = Math.round(usage.heapUsed / 1024 / 1024);

  if (heapUsedMB > 100) {
    // Alert at 100MB
    console.warn(`High memory usage: ${heapUsedMB}MB`);
  }

  return heapUsedMB;
}

Prevention:

  • Monitor memory usage with process.memoryUsage()
  • Process data in chunks instead of loading everything
  • Consider upgrading to paid plans for higher limits

Job Execution Issues

Jobs Not Running on Schedule

Symptoms:

  • Job shows as enabled but doesn’t execute
  • Last execution time doesn’t update

Troubleshooting Steps:

  1. Check Job Status:

    ✓ Verify job is enabled in dashboard
    ✓ Check cron expression is valid
    ✓ Confirm last execution time
  2. Validate Cron Expression:

    # Use the visual cron builder to verify
    # Common valid patterns:
    */5 * * * *   # Every 5 minutes
    0 9 * * *     # Daily at 9 AM UTC
    0 9 * * 1-5   # Weekdays at 9 AM UTC
  3. Test Manually:

    • Use “Run Now” button to test job execution
    • Check execution logs for errors
    • Verify job completes successfully

Jobs Failing Silently

Symptoms:

  • Job runs but shows no output
  • Exit code is 0 but expected results don’t appear

Debugging Steps:

// ✅ Add comprehensive logging
console.log("Job started at:", new Date().toISOString());
console.log("Environment check:", {
  nodeVersion: process.version,
  envVars: Object.keys(process.env).filter((key) => key.startsWith("API_")),
});

try {
  console.log("Starting main task...");
  const result = await performMainTask();
  console.log("Task completed:", result);
} catch (error) {
  console.error("Task failed:", error);
  throw error; // Important: re-throw to mark job as failed
} finally {
  console.log("Job finished at:", new Date().toISOString());
}

Environment Variables Not Working

Error Message: Cannot read property of undefined

Common Causes:

// ❌ Environment variable not set
const apiKey = process.env.API_KEY; // undefined
const url = apiKey.toString(); // Error: Cannot read property 'toString' of undefined

// ✅ Always check environment variables
const apiKey = process.env.API_KEY;
if (!apiKey) {
  throw new Error("API_KEY environment variable is required");
}

// ✅ Use default values where appropriate
const logLevel = process.env.LOG_LEVEL || "info";
const timeout = parseInt(process.env.TIMEOUT) || 30000;

Solutions:

  1. Verify variable names match exactly (case-sensitive)
  2. Check variables are set in job configuration
  3. Add validation at job start

Network and API Issues

External API Calls Failing

Common Error Messages:

  • ENOTFOUND: getaddrinfo ENOTFOUND
  • ECONNREFUSED: Connection refused
  • Timeout exceeded

Solutions:

// ✅ Robust API calling with retries
async function callExternalAPI(url, options = {}, maxRetries = 3) {
  const defaultOptions = {
    timeout: 30000,
    headers: {
      "User-Agent": "CronJS-Job/1.0",
      "Content-Type": "application/json",
    },
    ...options,
  };

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`API call attempt ${attempt} to: ${url}`);

      const controller = new AbortController();
      setTimeout(() => controller.abort(), defaultOptions.timeout);

      const response = await fetch(url, {
        ...defaultOptions,
        signal: controller.signal,
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      console.log("API call successful");
      return await response.json();
    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error.message);

      if (attempt === maxRetries) {
        throw new Error(
          `All ${maxRetries} API attempts failed: ${error.message}`
        );
      }

      // Exponential backoff
      const delay = 1000 * Math.pow(2, attempt - 1);
      console.log(`Waiting ${delay}ms before retry...`);
      await new Promise((resolve) => setTimeout(resolve, delay));
    }
  }
}

// Usage
try {
  const data = await callExternalAPI("https://api.example.com/data");
  console.log("Data received:", data);
} catch (error) {
  console.error("Failed to fetch data:", error.message);
  // Handle the failure appropriately
}

DNS Resolution Issues

Solutions:

// ✅ Use IP addresses for critical services (if available)
const apiUrl =
  process.env.USE_IP === "true"
    ? "http://192.168.1.100/api"
    : "https://api.example.com";

// ✅ Test DNS resolution
try {
  const testResponse = await fetch(
    "https://dns.google/resolve?name=api.example.com&type=A"
  );
  const dnsResult = await testResponse.json();
  console.log("DNS resolution:", dnsResult);
} catch (error) {
  console.warn("DNS test failed:", error.message);
}

Performance Issues

Slow Job Execution

Diagnostics:

// ✅ Performance profiling
async function profiledTask(taskName, taskFunction) {
  const startTime = Date.now();
  const startMemory = process.memoryUsage();

  console.log(`Starting ${taskName}...`);

  try {
    const result = await taskFunction();

    const endTime = Date.now();
    const endMemory = process.memoryUsage();

    console.log(`${taskName} completed:`, {
      duration: `${endTime - startTime}ms`,
      memoryUsed: `${Math.round(
        (endMemory.heapUsed - startMemory.heapUsed) / 1024 / 1024
      )}MB`,
      peakMemory: `${Math.round(endMemory.heapUsed / 1024 / 1024)}MB`,
    });

    return result;
  } catch (error) {
    console.error(
      `${taskName} failed after ${Date.now() - startTime}ms:`,
      error.message
    );
    throw error;
  }
}

// Usage
const data = await profiledTask("Data Fetch", () => fetchData());
const processed = await profiledTask("Data Processing", () =>
  processData(data)
);

Optimization Strategies:

// ✅ Parallel processing where possible
async function processItemsInParallel(items, maxConcurrency = 5) {
  const results = [];

  for (let i = 0; i < items.length; i += maxConcurrency) {
    const batch = items.slice(i, i + maxConcurrency);
    const batchPromises = batch.map((item) => processItem(item));

    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);

    console.log(
      `Processed ${Math.min(i + maxConcurrency, items.length)}/${
        items.length
      } items`
    );
  }

  return results;
}

// ✅ Efficient data processing
function processLargeArray(array) {
  // Use array methods that don't create intermediate arrays
  return array
    .filter((item) => item.isValid)
    .map((item) => transformItem(item))
    .reduce((acc, item) => {
      acc[item.category] = (acc[item.category] || 0) + item.value;
      return acc;
    }, {});
}

Authentication and Security Issues

Firebase Authentication Problems

Common Issues:

  • Session expired during job execution
  • Login fails with popup blockers

Solutions:

  1. Browser Settings:

    • Enable JavaScript and cookies
    • Disable popup blockers for app.cronjs.com
    • Clear browser cache and cookies
  2. Try Incognito Mode:

    • Isolates extension conflicts
    • Uses fresh session
  3. Alternative Auth Methods:

    • If Google OAuth fails, try email/password
    • If email fails, try Google OAuth

Email Verification Issues

Problem: Didn’t receive verification email

Solutions:

  1. Check spam/junk folder
  2. Wait 5-10 minutes for delivery
  3. Request new verification email
  4. Try different email address if problem persists

Getting Help and Support

Before Contacting Support

Gather Information:

  1. Job Details:

    • Job name and ID
    • Cron expression
    • Last successful execution time
  2. Error Information:

    • Complete error message
    • Execution logs
    • Steps to reproduce
  3. Environment:

    • Browser type and version
    • Time zone
    • Any recent changes

Contacting Support

Email: [email protected]

Include in Your Message:

  • Detailed description of the issue
  • Screenshots if relevant
  • Job execution logs
  • Steps you’ve already tried

Response Time:

  • Typical response within 24 hours
  • Critical issues prioritized

Self-Help Resources

Documentation:

Community:

  • Check GitHub discussions
  • Search existing documentation
  • Review common use cases

Debugging Checklist

When troubleshooting any issue:

✅ Basic Checks

  • Job is enabled in dashboard
  • Cron expression is valid
  • Environment variables are set correctly
  • JavaScript syntax is valid

✅ Execution Checks

  • Test job with “Run Now” button
  • Check execution logs for errors
  • Verify job completes within timeout
  • Monitor memory usage

✅ Network Checks

  • External APIs are accessible
  • Network requests have timeouts
  • Handle API rate limiting
  • Check DNS resolution

✅ Code Quality Checks

  • Add comprehensive logging
  • Implement error handling
  • Validate environment variables
  • Use try-catch blocks appropriately

Advanced Debugging

Debug Logging Pattern

// ✅ Comprehensive debug logging
function createLogger(jobName) {
  return {
    info: (message, data) => {
      console.log(
        `[${new Date().toISOString()}] [${jobName}] INFO: ${message}`,
        data ? JSON.stringify(data) : ""
      );
    },
    error: (message, error) => {
      console.error(
        `[${new Date().toISOString()}] [${jobName}] ERROR: ${message}`
      );
      if (error) {
        console.error("Error details:", error.message);
        console.error("Stack trace:", error.stack);
      }
    },
    warn: (message, data) => {
      console.warn(
        `[${new Date().toISOString()}] [${jobName}] WARN: ${message}`,
        data ? JSON.stringify(data) : ""
      );
    },
  };
}

// Usage
const log = createLogger("data-sync");
log.info("Starting data synchronization");
log.warn("API rate limit approaching", { remainingRequests: 10 });
log.error("Database connection failed", error);

Environment Validation

// ✅ Validate environment at job start
function validateEnvironment() {
  const required = ["API_URL", "API_KEY", "DATABASE_URL"];

  const missing = required.filter((env) => !process.env[env]);

  if (missing.length > 0) {
    throw new Error(
      `Missing required environment variables: ${missing.join(", ")}`
    );
  }

  console.log("Environment validation passed");
  console.log(
    "Available environment variables:",
    Object.keys(process.env).filter((key) => key.startsWith("API_"))
  );
}

// Call at job start
validateEnvironment();

Prevention Best Practices

Code Quality

  • Use TypeScript for better error detection
  • Implement comprehensive error handling
  • Add input validation
  • Use linting tools locally

Testing

  • Test jobs locally before deploying
  • Use “Run Now” to verify functionality
  • Test with different data scenarios
  • Validate error handling paths

Monitoring

  • Add performance logging
  • Monitor memory usage
  • Set up external health checks
  • Track success/failure rates

Security

  • Never log sensitive data
  • Validate all inputs
  • Use environment variables for secrets
  • Implement proper error messages

Remember: Most issues can be prevented with good logging, proper error handling, and thorough testing! 🛠️