I got a call from a client. Their new junior dev was trying to use a custom function I had built to update post meta, and it just wasn’t working. No errors, nothing in the logs, just silence. He was tearing his hair out, convinced he had broken the site. The real problem was a mismatch of expectations around WordPress type safety.
He was passing an entire post object to my function, but the function expected a simple integer: the post ID. My code was written “defensively,” so instead of blowing up it just quietly bailed. That is a common pattern in WordPress, and it can be a nightmare to debug.
The trap of “defensive” programming
Because WordPress has to maintain backward compatibility with ancient versions of PHP, we can’t always use modern typed properties like function update_meta(int $post_id, string $meta_value). Instead, we often rely on docblocks and manual checks inside the function. My first pass at it looked something like this. Sound familiar?
/**
* Update post meta for a given post.
*
* @param int $post_id The ID of the post.
* @param string $key The meta key.
* @param mixed $value The meta value.
*/
function my_safe_update_meta( $post_id, $key, $value ) {
if ( ! is_int( $post_id ) ) {
return; // It's not an integer, so just stop.
}
// ... rest of the update logic
update_post_meta( $post_id, $key, $value );
}My first thought was, “This is good. It prevents fatal errors.” And it did. But what it created instead was a silent failure. The code just stopped, giving zero feedback to the developer who called it wrong. That “safe” approach ended up costing my client hours of debugging time, which makes it expensive rather than safe.
A better way: fail loudly
For internal agency projects or client sites where you control the environment, favor strictness over silent flexibility. Your colleagues, and your future self, will thank you for it. Instead of quietly returning, the code should make some noise. There’s a good post on this over at carlalexander.ca.
A better version of that function tells the developer immediately that they’re doing it wrong.
/**
* Update post meta for a given post.
*
* @param int $post_id The ID of the post.
* @param string $key The meta key.
* @param mixed $value The meta value.
*/
function my_strict_update_meta( $post_id, $key, $value ) {
if ( ! is_int( $post_id ) ) {
_doing_it_wrong(
__FUNCTION__,
'Post ID must be an integer.',
'1.0.0'
);
return;
}
// ... rest of the update logic
update_post_meta( $post_id, $key, $value );
}By calling _doing_it_wrong(), we create a helpful notice for the developer. If they have debugging enabled, they get an immediate, actionable message explaining exactly what to fix, instead of guessing or hitting another silent failure.
So, what’s the point?
The right way to handle WordPress type safety depends entirely on who you’re writing the code for.
- Public plugins and themes: if your code is going out to the world, you have to be more defensive and flexible. You can’t control the environment, and a fatal error could take down someone’s site. The silent-but-safe approach is often the lesser of two evils here.
- Client work and internal projects: if you control the environment, be strict. Fail loudly and give clear feedback. It forces better coding habits and cuts debugging time sharply.
This stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.