Bluesky Invalid Handle: What It Means and How to Fix It

"⚠Invalid Handle" is not a typo warning and not a form error. It is what the Bluesky app prints when the API hands it the reserved string handle.invalid in place of your handle — which happens when your handle stops being able to prove it belongs to your account. The app's whole test is one line in src/lib/strings/handles.ts: return handle === 'handle.invalid'. Nothing about spelling, nothing about availability, nothing about which characters you used.

Distractify's explainer, near the top of the results, lands on "Finally, and perhaps most likely in this case, there could be a technical glitch on Bluesky's end." The rest explain the rules for typing a username at signup — at least three characters, no underscores, no emoji — which are real rules, and which have never once produced the words "Invalid Handle" in Bluesky's interface. So I went and measured the thing that actually causes it: thousands of accounts that pointed their own domain at themselves, pulled out of Bluesky's public identity log across nineteen monthly cohorts, re-checked today, with the broken ones diagnosed one by one.


What Does "Invalid Handle" Mean on Bluesky?

It means handle resolution failed, and handle resolution has to succeed in both directions. Forward: your domain publishes your DID, either as a DNS TXT record at _atproto.yourdomain.com with the value did=did:plc:…, or as plain text at https://yourdomain.com/.well-known/atproto-did. Backward: your DID document lists that domain in its alsoKnownAs field. The handle spec is blunt about why both are needed — "Handles should not be trusted or considered valid until the DID is also resolved and the current DID document is confirmed to link back to the handle" — because otherwise anyone could point a domain at your account and claim to be you.

When that check fails for good, the spec says services should use "the special handle value handle.invalid… to indicate that there is no bi-directionally valid handle for the given DID." It's a reserved string rather than a flag, and it can never collide with a real handle because .invalid is one of the eight TLDs the spec forbids outright, alongside .local, .onion and .internal. Kuba Suder, who has documented atproto identity more carefully than anyone, put the equivalence plainly last month: if neither resolution method returns anything, "the handle is not verified (which is what shows up on Bluesky as '⚠ Invalid Handle', and in the APIs usually as 'handle.invalid')." I'm not claiming to have found that. What nobody has written down is which other errors don't produce it.

That single meaning is worth pinning down, because five different things get called "invalid handle" in forum posts. Only the first one produces that phrase:

What you see Where it appears What it actually is
⚠Invalid Handle On a profile, in place of the handle Resolution failed; the API returned handle.invalid
"Username must only contain letters (a-z), numbers, and hyphens" Signup, under the username box Format check — underscores, dots and emoji are rejected here
"Username cannot be longer than 18 characters" Signup, under the username box Length check on the part before .bsky.social
"Failed to verify handle. Please try again." Settings → Change Handle, on pressing Verify Your domain didn't answer at all — record missing, still propagating, or on the wrong host
"Wrong DID returned from server. Received: …" Settings → Change Handle, on pressing Verify Your domain answered, but with somebody else's DID

Those signup strings come from the signup screen's own source, which validates a username against five named checks — handleChars, hyphenStartOrEnd, frontLengthNotTooShort (3), frontLengthNotTooLong (18) and totalLength (253). None of them can put the word "Invalid" on your profile. If you are staring at ⚠Invalid Handle, the username you typed is not the problem and never was.

The two Change Handle errors are worth separating from the badge as well, because they describe the opposite situation. "Failed to verify handle" means you never got the handle; ⚠Invalid Handle means you had it and lost it. The first is a setup problem you're actively debugging. The second is a thing that happened to you, quite possibly months ago, while you weren't looking.


How Often Do Bluesky Handles Go Invalid?

plc.directory will tell anyone who asks which accounts have ever swapped a .bsky.social handle for a domain of their own. I asked it for nineteen months of them — every operation in which an account on one of Bluesky's own servers declares a handle that isn't something.bsky.social — and then asked the public AppView what each of those accounts' handles is today.

Nineteen monthly cohorts, 3,390 custom-handle adoptions between November 2024 and July 2026, all re-checked on August 21, 2026. Six representative cohorts below; the total row is all nineteen, the other thirteen are left out for length rather than for effect:

Domain adopted Adoptions sampled Still on the domain ⚠Invalid Handle Back on .bsky.social Account gone
November 2024 472 83.7% 5.5% 4.9% 5.9%
March 2025 402 76.6% 5.2% 9.7% 8.5%
August 2025 155 76.8% 6.5% 10.3% 6.5%
December 2025 63 87.3% 3.2% 6.3% 3.2%
April 2026 31 87.1% 3.2% 3.2% 6.5%
July 2026 63 92.1% 0.0% 0.0% 7.9%
All 19 months 3,390 80.8% 4.5% 6.9% 7.7%

About one custom Bluesky handle in nine stops working, and 4.5% of the ones in my sample are showing ⚠Invalid Handle right now. Split the ways of losing it and 154 accounts (4.5%) are sitting broken, while 235 (6.9%) went back to a .bsky.social handle — 389 between them, 11.5% of everyone who tried. Both endings start from one event: the domain stops answering, and you either notice and retreat or you don't notice at all.

This is a known species of decay, just unmeasured here until now. "Zombies in Alternate Realities", an internet-measurement paper published in May 2026, tracks the same failure — DNS-based identity linkages outliving the domain registration behind them — and finds it in roughly 3% of Web PKI certificates for new domains, 15% of Maven Central namespaces and 24% of ENS on-chain imports. Bluesky's 4.5% sits at the low end of that range, and for a structural reason the paper names: systems that re-check the link keep breaking visibly, while systems that validate only once let the linkage rot silently. Bluesky re-resolves, so your handle goes conspicuously invalid instead of quietly continuing to point at whoever bought your domain next.

It's attrition, not a one-off. Cohorts thirteen months or older are at 5.0% broken and 7.0% reverted; cohorts ten months or younger are at 2.5% broken, and the July 2026 cohort — five weeks old — hasn't lost a single one yet. Domains don't fail on the day you configure them. They fail the day the renewal card expires, which is a year or two later, by which point nobody is watching the profile that depends on it.

One popular claim I can now put a number against: setup guides say that if you remove the TXT record, "your handle reverts to default within hours" — that exact sentence is in unil.ink's 2026 guide. It doesn't. There is no automatic fallback — the account keeps declaring a domain that no longer answers, and Bluesky keeps printing ⚠Invalid Handle until a human intervenes. Those 154 accounts are the proof; the oldest of them have been broken for well over a year.

The method is one command per span, run against plc.directory and the public AppView, both of which will answer anyone:

$ ./scripts/bsky_stats.py customhandles 2025-01:2025-01 20

cohort     adopted    still custom   handle.invalid       reverted           gone
2025-01       268     200   74.6%       20    7.5%     25    9.3%     23    8.6%

Read the frame carefully before quoting that number at anyone. It counts adoptions, not accounts — I sample two fifteen-minute windows a month and take whatever custom-handle operations fall inside, so a month is a sample of that month's adopters rather than a census of them. And the identity log is the only unbiased frame available: handle search can't return an account whose handle no longer resolves, so any sample built by searching handles is blind to exactly the population being measured. Terence Eden's survey of domain handles — 22,000 of them, pulled off the firehose in December 2024 — is the closest thing to prior art here, and it has that shape: it maps which TLDs people choose, from accounts busy enough to be posting. A handle that broke last spring never enters that sample.


Why Is My Bluesky Custom Domain Handle Invalid?

Because your domain stopped answering for you — not because Bluesky lost your account. I took the broken handles from the oldest cohorts and checked each one's DNS and web server directly:

Why it broke Handles Share
The domain is gone from DNS entirely 37 48.1%
The domain is live; the record was removed 31 40.3%
Both sides check out — resolution is just stale 7 9.1%
The record points at somebody else's DID 2 2.6%

That's 77 broken handles out of 1,581 adopters sampled from the November 2024 to March 2025 cohorts, each one re-queried over DNS-over-HTTPS and plain HTTPS on August 21, 2026. Nearly nine in ten are the account holder's own domain, not Bluesky. A dead registration and a deleted DNS record between them account for 88.4% of every broken handle I found.

The 9.1% deserves its own sentence, because it's the bucket everyone assumes is the whole chart. I checked three of those seven by hand in both directions. All three were configured correctly — gnuradio.org serves its DID from /.well-known/atproto-did, a personal .nl domain publishes a TXT record with exactly the right DID, and every one of their DID documents still names its handle in alsoKnownAs — and all three still read handle.invalid in the AppView. Bluesky has cached a failure and not gone back to look. That's a genuine platform bug, it's roughly one broken handle in eleven, and it's also precisely the case the official fix below is designed for.

In practice the causes fall out in this order:

  1. The domain lapsed. You stopped paying for it, or let it drop after a rebrand. The registrar takes it back, DNS goes dark, and your handle goes with it. This is the single biggest bucket.
  2. The DNS record went missing in a migration. Moving nameservers, switching to Cloudflare, or rebuilding a zone file will quietly drop a TXT record nobody remembers adding.
  3. A third party stopped serving the file. If your handle is you.somehost.com, the file at /.well-known/atproto-did is theirs, not yours. One account in my sample used a Substack subdomain that now returns a 404 HTML page where the DID used to be. (It is a perfectly nice 404 page. It is just not a DID.)
  4. The host is wrong for a subdomain handle. The TXT record for blog.example.com goes at _atproto.blog.example.com, not _atproto.example.com. This one bites on setup rather than later.
  5. Genuinely Bluesky's end. It happens — bsky.app said so in November 2024 ("If you're seeing 'Invalid Handle' on your profile, this should resolve on its own") and there's an open bug from September 2025 filed by a user whose DNS, DID and .well-known file all check out. It's real, it's just last on the list rather than first.

How Do You Fix an Invalid Handle on Bluesky?

Check first, then republish, then re-verify. The whole thing takes about three minutes if the domain is still yours.

  1. Find out which side is broken. Ask the internet what your domain says about you. curl works for both halves and needs nothing installed:

    curl -s "https://cloudflare-dns.com/dns-query?name=_atproto.YOURDOMAIN&type=TXT" \
         -H "accept: application/dns-json"
    curl -s "https://YOURDOMAIN/.well-known/atproto-did"
    

    You want one of them to come back with your DID. If the TXT lookup returns "Status": 3, the domain doesn't exist in DNS any more — go to step 4.

  2. Republish the proof. Add a TXT record with host _atproto and value did=did:plc:… (that exact prefix, no quotes around the DID), or upload your DID as a plain-text file at /.well-known/atproto-did — no trailing newline, Content-Type: text/plain. The app hands you your DID inside the Change Handle dialog itself, under "Value:", the moment you choose "I have my own domain". DNS propagation is minutes to an hour.

  3. Re-verify inside the app. Settings, then Change Handle, then I have my own domain, then type the handle you already have and hit Verify. Bluesky's advice from the August 2023 incident still describes it best: "reverify it by navigating to Settings > Change my handle > Type in your current handle > Verify DNS Record > Update. (Basically, update to the same handle.)"

  4. If the domain is gone, take a .bsky.social handle back. Same dialog, "Use a bsky.social domain" instead. You get to keep everything except the domain; on the numbers above, this is what most people in your position do.

Before you panic: an invalid handle costs you reachability, not your account. Follows are stored against your DID — Bluesky's own follow record carries subject: did:plc:…, and so does mine — so nothing detaches when the handle breaks, which is also why your follower count can look wrong without anybody having left. I looked up an affected account from the census: display name intact, 8 posts intact, all 76 followers intact, profile served normally when asked for by DID. What breaks is everything keyed on the name. com.atproto.identity.resolveHandle on the old handle returns Unable to resolve handle, getProfile on it returns Profile not found, and every link anyone ever saved to bsky.app/profile/yourdomain.com is now a dead end. You can still be found by display name in search — you just show up as ⚠Invalid Handle, which is not the impression a domain handle was supposed to make.


Is a Custom Bluesky Handle Still Worth It?

Yes, with a caveat the enthusiastic guides skip. A domain handle is Bluesky's original form of verification and still the only one you can grant yourself: @apnews.com is checkable by anyone in a way that a blue tick from a committee isn't. That's a genuinely good design, and it's why the accounts that actually get seen use it far more than the average signup does — in a sample of 300 accounts whose posts were surfacing in Bluesky's Discover feed today, 51 (17.0%) were on a custom domain, against 7 out of 1,000 taken from the followers of Bluesky's own @bsky.app account.

The caveat is that self-verification is a subscription, not a purchase. You are now the registrar, the DNS operator and the uptime guarantee for your own identity, and the failure mode is silent — nobody emails you when the record goes. If you set one up, put the domain on auto-renew, and re-run the two curl commands above once a year — a good moment to give the rest of the profile a look while you're in there. That's the entire maintenance burden, and it's the whole difference between the accounts that still have their handle and the ones that don't.

I had to implement this check myself, which is how I know there isn't a shortcut. Agent Sky — a $9-a-month following tool, free to start — resolves a handle by walking handle → DID → DID document, confirms the document claims the handle back, then runs it the other way and refuses the identity on a mismatch. That's the entire overlap between this post and the product, and I'd rather say so than stretch it.

A domain handle is the one credential on Bluesky that nobody can revoke but you. Which also means nobody but you will ever notice when it goes.


Quick FAQ

What does invalid handle mean on Bluesky? It means the API returned the reserved string handle.invalid for that account instead of a handle, and the app printed "⚠Invalid Handle" in its place. That happens when handle resolution fails: either the domain no longer publishes the account's DID, or the DID document no longer claims the domain. The AT Protocol handle spec requires both directions to check out — "Handles should not be trusted or considered valid until the DID is also resolved and the current DID document is confirmed to link back to the handle." It is not a spelling error, a ban, or a suspension.

Why is my Bluesky handle invalid? Because your domain stopped answering for you. Of 77 broken handles I diagnosed by hand, 48.1% had lost the domain entirely — it no longer resolves in DNS at all — and 40.3% still had a live domain that had simply stopped serving the _atproto TXT record or the /.well-known/atproto-did file. Another 2.6% pointed at somebody else's DID. Only 9.1% looked correctly configured on both sides when I checked, which is the honest size of the "it's a Bluesky glitch" bucket.

How do I fix an invalid handle on Bluesky? Republish the proof and then re-verify. Put a TXT record back at _atproto.yourdomain.com with the value did=<your DID>, or serve your DID as plain text at https://yourdomain.com/.well-known/atproto-did, then in the app go to Settings, Change Handle, enter the same handle again and save. Bluesky's own advice when this happened at scale in August 2023 was exactly that: "reverify it by navigating to Settings > Change my handle > Type in your current handle > Verify DNS Record > Update. (Basically, update to the same handle.)" If you no longer control the domain, switch back to a .bsky.social handle instead.

Does an invalid handle mean I lost my Bluesky account or my followers? No. Follows, posts and followers are all keyed to your DID, not your handle, so nothing detaches. I checked an affected account in my sample and it still had its display name, its 8 posts and all 76 of its followers. What you lose is reachability: com.atproto.identity.resolveHandle on the old handle returns "Unable to resolve handle", and anyone opening a link to your old profile URL gets "Profile not found".

Grow your Bluesky audience on autopilot

Agent Sky finds accounts in your niche, follows them at a safe pace, and unfollows the ones who never follow back. $9/month, free to start.