The Error
Fatal error: Uncaught Error: Call to undefined function some_function() in /var/www/html/app.php:42
Stack trace:
#0 {main}
thrown in /var/www/html/app.php on line 42
The function name after "Call to undefined function" tells you everything. curl_init โ missing extension. myhelper โ missing include. Read the full error before touching anything else โ that name is your entire investigation.
Root Causes
Four things trigger this error โ and only four:
- A PHP extension providing the function isn't enabled on this server
- The file defining the function was never included
- Namespace mismatch โ global functions need a
\prefix inside a namespace - Typo in the function name, or the function doesn't exist in your PHP version
Fix 1: Enable the Missing Extension
New server, new deployment, new team member's machine โ this is the most common culprit. Somewhere between your old environment and the new one, a PHP extension got left behind. Check whether the undefined function belongs to a known extension:
curl_init()โ curlimagecreate()โ gdmb_strlen()โ mbstringsodium_crypto_secretbox()โ sodiumldap_connect()โ ldapzip_open()โ zip
Check what's currently loaded:
php -m | grep curl
Or verify from PHP code:
<?php
var_dump(extension_loaded('curl'));
Install and enable on Ubuntu/Debian:
sudo apt install php8.2-curl php8.2-gd php8.2-mbstring
sudo systemctl restart php8.2-fpm
# or for Apache
sudo systemctl restart apache2
On CentOS/RHEL:
sudo dnf install php-curl php-gd php-mbstring
sudo systemctl restart php-fpm
Prefer editing php.ini directly? Find the active file first, then uncomment the extension line:
# Find your active php.ini
php --ini | grep "Loaded Configuration"
# Uncomment the relevant line
extension=curl
extension=gd
extension=mbstring
Restart your web server after any php.ini change โ the extension won't load otherwise.
Fix 2: Add the Missing Include
Your own functions and third-party libraries don't load themselves. If PHP hasn't seen the file defining a function, it simply doesn't exist at runtime. Check the top of your failing file:
<?php
// Must come before calling the function
require_once __DIR__ . '/helpers/user-functions.php';
// Now this works
create_user($data);
With Composer, one missing line kills more deployments than anything else โ the autoloader:
<?php
// Often absent on a fresh deployment
require_once __DIR__ . '/vendor/autoload.php';
// Now Composer packages resolve correctly
$client = new GuzzleHttp\Client();
Also check the order of your includes. PHP reads files top to bottom โ you can't call a function before its file is loaded.
Fix 3: Fix Namespace Issues
Inside a namespace, PHP searches for functions in that namespace first. It won't automatically fall back to global scope. Built-in and extension functions need a backslash prefix to force global namespace lookup:
<?php
namespace App\Services;
// FAILS โ PHP looks for App\Services\array_map()
$result = array_map('strtolower', $items);
// WORKS โ backslash forces global namespace
$result = \array_map('strtolower', $items);
Extension functions hit the same issue:
<?php
namespace App\Http;
// Fails
$ch = curl_init($url);
// Works
$ch = \curl_init($url);
Scattering backslashes everywhere gets messy fast. A cleaner fix โ declare use function at the top of the file once:
<?php
namespace App\Http;
use function curl_init;
use function curl_setopt;
use function curl_exec;
$ch = curl_init($url); // Works now
Fix 4: Wrong PHP Version or Typo
Some functions are version-gated. str_contains() landed in PHP 8.0. array_is_list() arrived in PHP 8.1. If you're running 7.4 and calling either one, you'll hit this error. Check your version first:
php --version
Confirm whether the function exists at all:
php -r "var_dump(function_exists('str_contains'));"
Stuck on an older PHP version? A polyfill gets you unstuck in under a minute:
<?php
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool {
return $needle === '' || strpos($haystack, $needle) !== false;
}
}
For typos, grep your codebase for where the function should have been defined:
grep -r "function the_function_name" /var/www/html/
Verify the Fix
Don't guess in the browser. Confirm from the CLI first:
# Check extension is loaded
php -r "echo extension_loaded('curl') ? 'curl: OK' : 'curl: MISSING';"
# Check function is accessible
php -r "echo function_exists('curl_init') ? 'OK' : 'MISSING';"
# Scan phpinfo output for the extension
php -r "phpinfo();" | grep -i curl
In development, add a guard before the problematic call. You'll get a clear, specific error message instead of a useless 500 page:
<?php
if (!function_exists('curl_init')) {
throw new \RuntimeException('curl extension not loaded โ install php-curl and restart your server');
}
Prevention
Declare PHP extension requirements in composer.json. This way, composer install fails immediately on a misconfigured server โ loudly, with a clear message โ rather than at runtime when a user hits the page:
{
"require": {
"php": "^8.1",
"ext-curl": "*",
"ext-mbstring": "*",
"ext-gd": "*"
}
}
Add a boot-time check in your application's initialization file for anything critical:
<?php
$required = ['curl', 'mbstring', 'pdo_mysql', 'gd'];
foreach ($required as $ext) {
if (!extension_loaded($ext)) {
throw new \RuntimeException("Missing required PHP extension: {$ext}");
}
}
Using Docker? Install all required extensions explicitly in your Dockerfile. When dev and production share the same image, this error stops appearing on new servers at 2 AM.

