Part 8 of 13 · Job Board

I Broke My Own Plugin by Cleaning It Up

A routine update, and suddenly the plugin would not activate, the fatal-error screen from the limo days back again. The debug log named it in one line, call to undefined function jab_schedule_sync, a function I had deliberately deleted weeks earlier when removing a scheduling feature, still being called from code I had forgotten. This post is the deleted-function fatal, why removals are riskier than additions, and the grep discipline that ends the whole category.

The log pointed at the crime scene precisely, my activation routine still invoked the dead function:

function jab_activate() {
    jab_register_types();
    flush_rewrite_rules();
    jab_schedule_sync();   // deleted weeks ago; fatal on every activation
}
register_activation_hook(__FILE__, 'jab_activate');

And a second call hid in the settings-save handler, which had refreshed the schedule when sync settings changed. The removal had deleted the definition and missed two of its callers, and PHP’s timing rules explain the delayed detonation, calls to missing functions only fail when execution reaches them, so the plugin ran fine for weeks because nobody activated it or touched those settings, the corpse in the code waiting for a code path. Deletions are riskier than additions for exactly this reason, an addition fails where you are looking, a deletion fails wherever the thing was referenced, which is a set you must discover.

The fix took a minute, remove both stale calls. The discipline that makes it never happen again took one habit, when removing anything, search for every reference before and after the removal:

// before deleting jab_schedule_sync, and again after:
// grep -rn "jab_schedule_sync" .
// remove the definition AND every call the search reveals; then grep once more
// the final search must return nothing

Search the name, remove definition and callers together, search again expecting zero, three steps that convert removal from memory work into mechanical work. The namespacing habit from post one quietly helps here too, a distinctive jab_ prefixed name greps cleanly with no false matches, one more dividend from boring prefixes. And the deeper takeaway travels beyond PHP, any removal, a function, a setting, a database column, a file, has a reference set larger than your memory of it, and tools, not recollection, are how you find the edges.

A few things people ask me about this

Why did the missing function not crash immediately when I deleted it? PHP resolves function calls at execution, not at load. The fatal waits until a code path actually reaches the stale call, activation hooks and settings saves are classic delayed paths.

What is the fastest way to find all callers before removing something? A project-wide text search for the exact name, grep or your editor’s find-in-files. Prefixed, distinctive names make the results exact, run it before and after the removal.

Next

With the engine stable again, the board’s search presence needed its structured data, and JobPosting schema came with a Google complaint and a temptation to fabricate. That honesty story is the next post.

Leave a Reply

Your email address will not be published. Required fields are marked *