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.

Jaco Pastorius: The Chicken/Soul Intro Chord Changes

Note: I’ve copied this over from my Patreon, mainly as an SEO experiment. These days I’m generally keeping the music-related stuff on YouTube and, to a lesser extent, Patreon, but I want to see whether this post is more “google-able” here or there.


This probably doesn’t warrant a full YouTube video. (Then again, maybe it does, but I have a gig this afternoon and I don’t have time to make one right now!)

The big band I play in (the one that has a gig this afternoon) has “The Chicken” in our books as an encore/jam. I don’t really use the sheet music for it at all because… well, every bass player should know how to play “The Chicken.” It’s just a 12-bar blues in B♭ with a funky groove.

“The Chicken” was written by Pee Wee Ellis when he was in the James Brown band, and was famously covered by the Jaco Pastorius Big Band in the early 1980s. The main part of the song, as I said, is a straightforward blues, but the Jaco recording begins with the “Soul Intro,” a gospel-infused, slow 3/4 intro.

My sheet music has a transcription of what Jaco plays in this intro, and I’ve memorized it, but it always helps to understand the underlying form when I’m going to be playing something like this.

Here’s the part as written (re-engraved by me in MuseScore so I can overlay the chords later; note that I’ve omitted a bunch of articulation marks because they’re not relevant here):

Once you’ve worked out where to play these lines on the fingerboard, this isn’t really that difficult to play. But I find that it’s a lot easier to work out where to play the lines if I understand the underlying chord structure.

I only have two things to go by here: this written out bass part, and the recording. I checked the rest of the books in our band library. I guess there’s no piano part, because the piano player is using the guitar part, and the guitar is just tacet in the intro. There’s also no score, and of course the changes for this wouldn’t be written in the horn parts. So, I’m on my own.

First I tried working out the chords just by looking at the bass part on its own. That got me… pretty close. But then I listened to the recording and tried playing the chords on the keyboard along with the music, and I discovered I was a bit off on a couple of them. (Specifically, it was minor details like treating the opening chord as a B♭Maj7 instead of just B♭, missing a passing ♭VII/II, not correctly guessing that the part where I’m just playing F octaves is, in fact, an F7sus4… stuff like that.)

Anyway, once I had both examined the written bass part and played my keyboard along with the recording, I came up with the chords shown below. How do you think I did?

To summarize in text, here are the changes as I have them (using percent signs for measure repeats):

B♭ | % | D7 | % |
Gm7 | B♭7/D | C6 | % |
D♭ | % | F7 | % |
G♭6 | % | F7sus4 | % |
% | % | E♭ Gm/D Cm7 | B♭ |
E♭7 | Bb6 ||

I’m still unsure about that 6 on the C6 in bar 7. It sounds weird played on the keyboard, so it’s mainly for the benefit of the bassist.

(Of course, I only noticed after I published this that MuseScore had notated the G♭s as F#s in bars 13 and 14. They’re G♭s in the original.)

Maybe I don’t really need a formal ADHD diagnosis

My undiagnosed ADHD brain this morning (abbreviated):

While making coffee, decided I was going to have a bagel. Got out the cream cheese and realized it was moldy. Washed out the container and went to throw it in the recycling. Discovered we didn’t have a paper bag for recycling under the sink. Went to the basement landing where we keep the paper bags. Discovered the motion sensor light wasn’t working. Replaced the bulb, but found both the bulb and the sensor were dead. Threw them both away and just installed a new bulb directly in the socket. Went back to the kitchen (surprisingly, remembering the paper bag for recycling!) and made a different breakfast since there was no cream cheese for the bagel. While eating, watched some YouTube videos. Glanced at my own YouTube channel stats, and went off on a stream of consciousness writing a script for a new YouTube video I’ll probably never make. Decided to have a second cup of coffee. While the water was heating up, noticed the stove needed to be cleaned. Took off the knobs to soak them in the sink, but found the sink drain was clogged. Took apart the sink drain to clear the clog. Realized the whole thing kind of needs to be replaced, but somehow managed to restrain myself from going to the hardware store right that instant. Cleared the clog and got things reassembled. Made my second cup of coffee. Decided I needed to document the morning here.

Still haven’t even started on my actual work for the day and it’s almost noon.

UoP: Now featuring “Dark Mode”

I have generally had an aversion to dark mode on devices. It’s not that I object to it aesthetically; I do think it objectively looks better most of the time. And it’s not just that I’m an old curmudgeon who wishes we were still running Mac System 7 on Motorola 68000 series processors, although I do have fond nostalgia for those times.

It’s really my eyes. And even then, it’s not that I’m an old curmudgeon with failing eyes — although my eyes have definitely deteriorated through my 40s and into my 50s.

It’s my astigmatism.

I don’t just have astigmatism; I have weird astigmatism. The axis between my two eyes is turned almost 90 degrees. I can’t get glasses with full correction because it forces the muscles in my eyes in opposing directions in such a way to give me an almost instant headache. Fortunately, I can correct it enough to see reasonably well. But I digress…

Dark mode is difficult for people with astigmatism. You know those optical illusion tricks where you stare at a dot in the center of a reversed-color image for 60 seconds, then look at a blank wall and the “burn in” in your eyes shows you the actual image? My eyes do that with white text on a dark background after about 10 seconds, to the point where I can no longer read anything on the screen.

So, I rarely use dark mode. But I know I’m in a small minority.

CSS media queries now include a prefers-color-scheme setting that lets you design your website to automatically adjust to the user’s light/dark mode preference. Combine that with CSS variables and it’s super easy to add dark mode to your website. In fact, I decided this morning to add dark mode to this site, and it only took me about 5 minutes. Choosing colors that actually look good can be a bit trickier, and you have to make judgment calls about some of your accent colors.

I decided to primarily just invert the neutral colors (white, black, grays) on my site, and I used this color inverter tool to find appropriate replacements. I didn’t change most of my accent colors, because they’re part of my brand, but I did switch to a lighter shade of blue for links, since I do already have two blues in my color palette.

I used this Dark Mode in CSS Guide for a few additional improvements, specifically using filter() to adjust the brightness and contrast on images (except my logo), as well as to tone down the intensity of the PrismJS code blocks, since — at least with the implementation I’m using — it doesn’t seem to support automatic color modes.

If you’ve got your device on dark mode, or “automatic” and it’s nighttime, you should see dark mode right now! If you’re like me though, you’ll only see it if you temporarily turn on dark mode for testing purposes. And now that I’ve done this, I’m switching back to light.

Toast (a poem)

I stand motionless
Staring into the hot orange glow
Tick… tick…
Seconds become minutes
Become years
Tick… tick…
The hot orange burns my eyes
As I feel death's icy grip upon my shoulder
Tick… tick…
Ding!
My toast is ready