From d91c6124c87fa8746495d12024f188224920c362 Mon Sep 17 00:00:00 2001 From: Bryan Brooks Date: Tue, 24 Feb 2026 19:30:15 -0600 Subject: [PATCH] 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. --- gateway/src/index.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/gateway/src/index.ts b/gateway/src/index.ts index eecea51..f5c5a6b 100644 --- a/gateway/src/index.ts +++ b/gateway/src/index.ts @@ -333,6 +333,28 @@ async function main(): Promise { }); } + // Handle AT Protocol identity resolution failures (invalid/unresolvable handles) + if (err.constructor?.name === 'OAuthResolverError') { + const cause = (err as any).cause; + const handleMatch = err.message.match(/identity:\s*(.+)/); + const handle = handleMatch ? handleMatch[1] : 'unknown'; + let userMessage = `Could not resolve handle "${handle}". `; + + if (cause?.message?.includes('does not resolve to a DID')) { + userMessage += 'This handle has no _atproto DNS TXT record. Ensure the handle is configured on a PDS with proper DNS records.'; + } else if (cause?.message?.includes('not found')) { + userMessage += 'The handle was not found. Check that the handle is spelled correctly and the PDS is reachable.'; + } else { + userMessage += 'The AT Protocol identity could not be verified. Check that the handle exists and the PDS is online.'; + } + + console.error(`Identity resolution failed for "${handle}":`, cause?.message || err.message); + return res.status(400).json({ + error: 'handle_resolution_failed', + message: userMessage, + }); + } + // Log unexpected errors console.error('Unhandled error:', err); res.status(500).json({ -- knotmirror 0.0.1