AtAuth
7

Configure Feed

Select the types of activity you want to include in your feed.

fix: return descriptive 400 for unresolvable AT Protocol handles

OAuthResolverError was falling through to the generic 500 handler,
giving users no useful feedback when they mistyped their handle.
Now returns 400 with specific guidance about DNS records or handle
spelling.

Bryan Brooks (Feb 24, 2026, 7:30 PM -0600) d91c6124 ed536d4c

+22
+22
gateway/src/index.ts
··· 333 333 }); 334 334 } 335 335 336 + // Handle AT Protocol identity resolution failures (invalid/unresolvable handles) 337 + if (err.constructor?.name === 'OAuthResolverError') { 338 + const cause = (err as any).cause; 339 + const handleMatch = err.message.match(/identity:\s*(.+)/); 340 + const handle = handleMatch ? handleMatch[1] : 'unknown'; 341 + let userMessage = `Could not resolve handle "${handle}". `; 342 + 343 + if (cause?.message?.includes('does not resolve to a DID')) { 344 + userMessage += 'This handle has no _atproto DNS TXT record. Ensure the handle is configured on a PDS with proper DNS records.'; 345 + } else if (cause?.message?.includes('not found')) { 346 + userMessage += 'The handle was not found. Check that the handle is spelled correctly and the PDS is reachable.'; 347 + } else { 348 + userMessage += 'The AT Protocol identity could not be verified. Check that the handle exists and the PDS is online.'; 349 + } 350 + 351 + console.error(`Identity resolution failed for "${handle}":`, cause?.message || err.message); 352 + return res.status(400).json({ 353 + error: 'handle_resolution_failed', 354 + message: userMessage, 355 + }); 356 + } 357 + 336 358 // Log unexpected errors 337 359 console.error('Unhandled error:', err); 338 360 res.status(500).json({