Laravel Forge scheduled commands often fail due to missing environment variables, incorrect cron syntax, or permission errors. The most common fix is ensuring the php binary path matches your PHP version and that the .env file contains all necessary database credentials. Verify the cron job exists in the Forge dashboard and check server logs for specific error messages to isolate the root cause.
Verifying Cron Job Configuration
The first step in troubleshooting Laravel Forge scheduled tasks is to ensure the cron job itself is correctly configured within the Forge interface. Forge automatically generates a cron entry for each server, but it is crucial to verify that the command string is accurate. Navigate to the "Cron Jobs" section of your server settings in the Forge dashboard. Look for the line that executes the Laravel scheduler. It typically looks like this:* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
If this line is missing or commented out, the scheduler will never trigger. Ensure there are no typos in the path to your project directory. The path must be absolute, not relative. A common mistake is using a tilde (~) for the home directory, which cron jobs do not expand correctly. Always use the full path starting with /home/forge/ or whatever your user directory is. Additionally, check if the command is duplicated. Multiple entries can cause conflicts or redundant processing, leading to unexpected behavior.
Checking Environment Variables
Scheduled commands run in a non-interactive shell environment. This means they do not have access to your local development environment variables unless explicitly defined. If your command relies on database connections, queue drivers, or API keys, these must be present in your.env file on the production server. Often, developers update their local .env file but forget to deploy the changes to the live server via Git or manually.
Verify that your .env file contains the correct values for DB_HOST, DB_DATABASE, and DB_USERNAME. If you are using services like Redis or AWS S3, ensure those keys are also set. You can test if the environment variables are loading by running a simple command:
php artisan tinker
>>> env('APP_NAME')
If this returns null, your environment is not being loaded correctly. In some cases, you may need to clear the config cache after updating the .env file:
php artisan config:clear
This ensures that Laravel reads the latest configuration from the disk rather than a cached version. If you are deploying via Git, ensure that your deployment script includes a step to publish or sync the .env file. Without these variables, your scheduled task might fail silently or throw an exception that prevents subsequent tasks from running.
Inspecting Server Logs
When a scheduled command fails, Laravel does not always provide immediate feedback in the terminal. Instead, errors are written to log files. The primary location for these logs is/storage/logs/laravel.log within your project directory. Use the tail command to monitor this file in real-time while the cron job is scheduled to run:
tail -f /home/forge/your-app/storage/logs/laravel.log
Look for exceptions such as RuntimeException or Symfony\Component\Process\Exception\ProcessFailedException. These errors often indicate that a dependency is missing or a configuration setting is invalid. If the log is empty when the job should have run, the issue likely lies with the cron job itself not triggering, rather than the code failing.
You should also check the system-level logs for any PHP errors. These are usually found in /var/log/php*/error.log. If PHP crashes during execution, it will not write to the Laravel log. Checking these system logs can reveal memory limit issues or extension problems. For example, if you are using a package that requires the gd extension for image processing, and it is not installed, PHP will throw a fatal error. Installing the missing extension and restarting PHP-FPM can resolve this.
Permission Issues
File permissions are another frequent culprit. The web server user (usuallywww-data or forge) must have write access to the storage and bootstrap/cache directories. If the scheduled command attempts to write logs or cache data, it will fail if permissions are restrictive. Run the following command to ensure proper ownership:
sudo chown -R forge:forge /home/forge/your-app
Additionally, ensure that the executable bit is set on the artisan file, although this is rarely an issue on standard Linux distributions. If you are using a custom PHP binary, ensure it has execute permissions. Incorrect permissions can cause the cron job to exit immediately with a status code indicating a permission denied error.
Testing Command Execution Manually
To isolate whether the issue is with the scheduler or the command itself, try running the command manually via SSH. Connect to your server and navigate to your project root. Execute:php artisan your:command
If this runs successfully, the code is fine, and the problem is definitely with the cron configuration or environment. If it fails, debug the command directly. You can also force the scheduler to run all pending jobs by using:
php artisan schedule:run
This simulates what the cron job would do. Check the output for any errors. If it works manually but not via cron, the difference is almost certainly the environment variables or the working directory. Ensure your cron job uses the cd command to change into the project directory before calling php artisan, as shown in the cron verification section.
Frequently Asked Questions
Why does my scheduled command work locally but not on Forge?
Local environments often load variables from your OS or IDE, whereas Forge cron jobs rely strictly on the.env file. Ensure all production-specific credentials are present in the server's .env file and that the config cache is cleared after deployment.
How do I check if the cron job is actually running?
Check the last modification time of/storage/logs/laravel.log. If it updates every minute, the cron is firing. You can also add a simple log statement at the start of your command to confirm execution frequency.
Can I use different PHP versions for scheduled commands?
No, the cron job uses the default PHP version configured for the server in Forge. If you need a specific version, you must change the server's PHP version globally or specify the full path to the desired PHP binary in the cron command.What causes the "Command not found" error in cron?
This usually happens because the PATH environment variable is not set in the cron job. Using the full path to thephp binary, such as /usr/bin/php, resolves this issue. You can find the path by running which php in your terminal.
Should I commit the .env file to Git?
Never commit the.env file containing secrets to Git. Instead, use a template like .env.example and manage production variables through Forge's environment variables section or a secure deployment script that injects them securely.