| @@ -110,6 +110,40 @@ async function readErrorMessage(response: Response, fallbackMessage: string): Pr · 109 unmodified lines |
| 110 | 110 | return text || fallbackMessage; |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | +const INVALID_BOOTSTRAP_CREDENTIAL_MESSAGES = new Set([ |
| 114 | + "Invalid bootstrap credential.", |
| 115 | + "Unknown bootstrap credential.", |
| 116 | +]); |
| 117 | + |
| 118 | +function parseBootstrapErrorMessage(message: string): string { |
| 119 | + const trimmed = message.trim(); |
| 120 | + if (trimmed.length === 0) { |
| 121 | + return ""; |
| 122 | + } |
| 123 | + |
| 124 | + try { |
| 125 | + const parsed = JSON.parse(trimmed) as { |
| 126 | + error?: unknown; |
| 127 | + }; |
| 128 | + if (typeof parsed.error === "string" && parsed.error.trim().length > 0) { |
| 129 | + return parsed.error.trim(); |
| 130 | + } |
| 131 | + } catch { |
| 132 | + // Not JSON; fall back to plain text. |
| 133 | + } |
| 134 | + |
| 135 | + return trimmed; |
| 136 | +} |
| 137 | + |
| 138 | +function toFriendlyBootstrapErrorMessage(status: number, message: string): string { |
| 139 | + const parsedMessage = parseBootstrapErrorMessage(message); |
| 140 | + if (status === 401 && INVALID_BOOTSTRAP_CREDENTIAL_MESSAGES.has(parsedMessage)) { |
| 141 | + return "Invalid pairing token. Check the token and try again."; |
| 142 | + } |
| 143 | + |
| 144 | + return parsedMessage; |
| 145 | +} |
| 146 | + |
| 113 | 147 | async function exchangeBootstrapCredential(credential: string): Promise<AuthBootstrapResult> { |
| 114 | 148 | return retryTransientBootstrap(async () => { |
| 115 | 149 | const payload: AuthBootstrapInput = { credential }; |
| @@ -123,7 +157,7 @@ async function exchangeBootstrapCredential(credential: string): Promise<AuthBoot · 7 unmodified lines |
| 123 | 157 | }); |
| 124 | 158 | |
| 125 | 159 | if (!response.ok) { |
| 126 | | − const message = await response.text(); |
| 160 | + const message = toFriendlyBootstrapErrorMessage(response.status, await response.text()); |
| 127 | 161 | throw new BootstrapHttpError({ |
| 128 | 162 | message: message || `Failed to bootstrap auth session (${response.status}).`, |
| 129 | 163 | status: response.status, |