WordPress capabilities crisis

This post originally appeared on the blog for my ICS Calendar plugin.


I’m not just a WordPress plugin developer… I’m also a WordPress user.

This very website, which sells a WordPress plugin, runs WordPress. And a bunch of other WordPress plugins, most of which I didn’t develop.

This morning, I found I suddenly was unable to log into the WordPress admin. Well… I could log in. But I couldn’t access any admin pages. At first I worried the site had been hacked. Although I’m aware of most of the typical hack vectors and have taken reasonable standard precautions to prevent that.

What happened today was unlike anything I had ever encountered before. It started with a fatal error in Gravity SMTP — the plugin I use for sending emails. I’m not throwing Gravity under the bus. What happened was totally not their fault; their plugin just happened to be the canary in the coalmine.

Specifically, I got this error:

Fatal error: Uncaught Error: Call to a member function add_cap() on null in /wp-content/plugins/gravitysmtp/includes/users/class-roles.php:105

That led me on a wild goose chase of deactivating plugins, reinstalling WordPress core, rebooting my server, manually editing records in the database… the stuff they tell you you “shouldn’t” do, but I know how to do because I’ve been doing this since before the rules existed. (In fact, some of my youthful mistakes in the late 1990s and early 2000s probably helped define the rules.)

None of that got me anywhere. One thing I did find that I thought would solve the problem was my discovery that the record in the wp_options data table that stores all of the roles and capabilities was missing. How does that happen?

A hack was unlikely. Data records do get corrupted or accidentally deleted from time to time. It’s possible that it was an obscure bug in a plugin, or more specifically a plugin conflict. I may never know.

Anyway, I tried to fix that by copying the corresponding record from the database of another WordPress site. But even though the {$table_prefix}_user_roles option was back, WordPress wasn’t reading it.

At least I knew the realm of the problem at this point, so I searched for another answer, and that’s when I found this helpful tutorial from Hostinger.

This requires using WP-CLI to run some commands over SSH. I didn’t have WP-CLI installed, but fortunately that’s easy to do.

Once I had it installed I ran the wp role list command, and was alarmed to get back an empty list. So maybe there was a second option I would have needed to restore in the database, but that didn’t matter because by now I was at the command line and could just do the rest of what I needed right there.

First, I needed to restore all of the core WordPress roles. That required a few simple commands:

wp role reset administrator
wp role reset editor
wp role reset author
wp role reset contributor
wp role reset subscriber

With the roles reset, I was actually able to access the WP admin area again, and I could proceed to the next step: the e-commerce portion of this site, unsurprisingly, is built on WooCommerce, so I needed to get Woo’s custom roles reset. The WP-CLI stuff only works for WordPress default roles, not custom roles created by plugins.

I checked my Users list, and sure enough all of the customers just had “None” listed as their role. I was reasonably confident the data was intact, and it was just that the “Customer” role was undefined.

Most plugins that make these kinds of data modifications have special functions that run on activation, so I just deactivated and reactivated all of my plugins, and that seems to have reset everything.

(Yes, I could have just run the wp role reset --all command to take care of all of that at once, but I didn’t read that far in the tutorial!)

In conclusion, this post is intended to serve two purposes:

  1. To help other WordPress site admins who might encounter this weird and alarming problem.
  2. To explain to ICS Calendar Pro customers what was going on if they had any trouble accessing the site earlier today.

While this problem is certainly weird and alarming, it is also exceedingly rare. I have built, literally, hundreds of WordPress websites in the past 18 years. This is the first time I have ever encountered this issue. Let’s hope it’s the last. But if not, at least now I know what to do, and can jump straight to a 2-minute solution using WP-CLI, instead of fumbling around in the dark for 2 hours like I did this morning.

Follow-up on my post about getting an iPhone 5c on the eve of the iPhone 6 announcement

So, a few weeks back, just 4 days before the iPhone 6 announcement to be specific, I wrote here that I wanted an iPhone 5c. I had been coveting the funky colors and unashamed plastic of them since they’d been announced, and I’d seen enough leaked photos and specs for the iPhone 6 that I already knew, if it lived up to the rumors, that I didn’t really want one.

The day after I wrote that blog post, I went for it. We went to the Apple Store and bought no fewer than three iPhone 5c’s, in fact — two 32 GB units and one 16 GB unit for the boy, who’s now in middle school and needs a way to communicate with us given his newfound independence — and switched from Verizon to T-Mobile in the process.

The rationale: regardless of what they did keep, I knew (or at least reasonably assumed) Apple would be discontinuing the 32 GB 5c once the 6 was announced, and I also knew that 32 GB was the “sweet spot” for my iPhone storage capacity needs. My faltering iPhone 5 had 64 GB of storage, and I had never used more than about 35 GB of that… and even then only by unnecessarily carrying around a half dozen full-length, HD movies on the device.

So it was that on the weekend before the iPhone 6 announcement, I became the proud owner of a gaudy, banana-yellow iPhone 5c. And it was good.

T-Mobile, so far, has been great. The guys at the T-Mobile store where I had to go the next day to activate my phone were fast and knew what they were doing, and T-Mobile’s service has been outstanding, with voice call clarity and LTE reliability I could never even have imagined possible with Verizon, at a little over half the cost.

But my joy didn’t last long. Not because the iPhone 6 surprised me — it didn’t. At all. But because less than 24 hours after I took my iPhone 5c out of the box, it fell out of my pocket as I got out of the car in our garage, and suffered a permanent ding in the plastic on the lower right corner. Fortunately it was very, very small. But it was big enough to consume a significant portion of my attention for the next two weeks. I touched it constantly. I stared closely at it, willing it to disappear.

It did not disappear.

On the night we bought the iPhones, I rationalized the obviously ludicrous purchase by noting Apple’s 14-day return policy. That gave me until the day after the iPhone 6 would go on sale to change my mind.

As it happens, a coworker had preordered the iPhone 6, and it arrived at the studio on Friday. I took a look at it. I held it. I even put it in my pocket. It was not bad… definitely not as obnoxiously big as I had expected. But I still didn’t want it. I would live with my iPhone 5c, scratch and all, for a year at least, until the next round of updates.

But then, the next morning, 14 days after my purchase, and therefore the last day I could return the 5c to the Apple Store, I was idly browsing Apple’s website.

The first thing I noticed was that the 5c, now the lowest-end iPhone, is now only available in an 8 GB size. I had assumed they’d keep the 16 GB around. 8 GB is just stupid now. But whatever. I had my 32 GB unit. I was happy.

Of course I was aware that the 5s had been bumped down to the mid-range level previously occupied by the 5c. Which meant that if I’d just waited a few days, I could’ve gotten a 5s for the price of a 5c. I didn’t really care. I knew it was faster, had a slightly better camera, and had TouchID, which I didn’t think I wanted. I was fine with my banana-colored 5c.

Until I looked at the price. The 32 GB 5s was now $50 cheaper than what I had paid for the two 32 GB 5c’s we had bought 14 days earlier. That meant we could take them back, upgrade to 5s’s, and get $100 back! Hell yes.

Not only that, I could get rid of the ding in the plastic that had plagued my mind for two weeks.

So later that afternoon, we trekked back to the Apple Store, past all of the people queued up outside to get iPhone 6’s, and straight to a blue-shirted employee who was more than happy to work with us and never once even glanced in the direction of the ding. 15 minutes later, we had exchanged our 5c’s for 5s’s and had gotten a big credit back to our bank account.

I used part of my $50 refund to buy a bright yellow case for my “space gray” iPhone 5s.

So much for the free market

I am not a free market capitalist. I don’t believe that those whose primary objective is to obtain as much money as possible can always be trusted to do so scrupulously (or, for that matter, competently). I also do not see the government as a malevolent force. In the words of Abraham Lincoln, ours is a “government of the people, by the people, and for the people.” The government is us. This, given the current widespread disdain of “Big Government”, would suggest that America has been struggling through an extended period of self-loathing. But mostly it just means that the government exists to manifest the will of the people.

Is it the people’s will that we give investment banks $700 billion (that’s about $2300 for — or rather, from — every single one of us, infants and elderly included, by the way) as a reward for proving themselves wrong about the merits of deregulation? Government is bad when it keeps them in line, but it’s good when it saves them from suffering the consequences of their mistakes. Wonderful for the rest of us.

A couple of other developments today have my blood boiling at an even more rapid pace than it already was: first, I learned that Congress is also preparing to give $25 billion to the auto industry to upgrade its outdated plants to produce more fuel-efficient cars. Fuel efficiency is a good thing, and if GM, Ford and Chrysler manage to improve it, rock on. But let’s be honest: this has nothing to do with protecting the environment, or even reducing our dependence on foreign oil. It’s about saving the asses of more free market capitalists who suddenly find themselves facing the music over years of bloated incompetence and obscene executive salaries.

Second, John McCain has proudly declared his intention to suspend campaigning, and also wants to postpone Friday’s debate with Barack Obama. Never mind the fact that suspending campaigning was actually Obama’s idea (O called M this morning to discuss the idea of a joint announcement, then M jumped the gun and stole the thunder). How exactly does it benefit the people, who very soon will head to the polls and hand over the reins of government to one of these guys, to postpone the debate? Is the Senate really going to be in session at 9 PM this Friday? If so, I’m sure they’ll give themselves overtime pay.

Meanwhile, the rest of us might spend the weekend contemplating this.

How should we interpret Warren Buffet’s plan to invest in Goldman Sachs?

I’ll admit I am way out of my area of expertise on this. I prefer to remain as ignorant of the goings-on of Wall Street as possible. But since Wall Street has made itself significantly more relevant to the day-to-day lives of average Americans over the past week or two, I’ve been paying more attention.

Needless to say (well, maybe not, since I’m saying it), I’m not incredibly enthusiastic about the plan to give $700 billion from the taxpayers to these fail(ed/ing) investment banks. It’s probably a better way to spend the money than the war in Iraq, but not by much. It certainly puts some perspective on Washington’s reluctance to invest in things that would actually improve the lives of the people who are footing the bill (roads, schools, healthcare, etc.).

Here’s something else that puts some perspective on it: according to an article in today’s New York Times, Warren Buffet, investor extraordinaire, is planning to invest $5 billion, via his Berkshire Hathaway company (which clearly has not wasted the money on its website), in Goldman Sachs, one of the ailing investment banks. Now as I see it, Buffet is trying to help salvage the situation, and (being a smart capitalist) he’s also making an investment he believes will pay off for his company. But I think there’s something deeper and perhaps even more altruistic than simply providing a cushion for Wall Street CEOs who are fearful that their golden parachutes might not fully deploy.

Buffet’s move looks, to me, like a lesson by example to other ultra-rich investors: you might just be able to fix this problem yourselves, without dragging the rest of us down with a poorly-reasoned public bailout, the effects of which remain to be seen but are likely to be even more disastrous and long-lasting than the crisis they’re designed to avert.

Update: Then again, never mind.