Fix PHP Fatal Error: Call to undefined function โ€” 4 Causes and Fixes

intermediate๐Ÿ˜ PHP2026-03-19| PHP 7.x/8.x on Linux (Ubuntu/Debian/CentOS), Windows (WAMP/XAMPP), macOS โ€” Apache or Nginx + PHP-FPM

Error Message

Fatal error: Uncaught Error: Call to undefined function
#php#function#undefined#extension

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() โ†’ curl
  • imagecreate() โ†’ gd
  • mb_strlen() โ†’ mbstring
  • sodium_crypto_secretbox() โ†’ sodium
  • ldap_connect() โ†’ ldap
  • zip_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.

Related Error Notes