| ... | ... | @@ -110,6 +110,40 @@ async function readErrorMessage(response: Response, fallbackMessage: string): Pr |
| 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 |
| 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, |