Skip to content

Commit bee6025

Browse files
author
SentienceDEV
committed
pass gateway error exception messages
1 parent 9aa48ce commit bee6025

2 files changed

Lines changed: 74 additions & 5 deletions

File tree

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
export { SentienceBrowser, PermissionPolicy } from './browser';
6-
export { snapshot, SnapshotOptions } from './snapshot';
6+
export { snapshot, SnapshotOptions, SnapshotGatewayError } from './snapshot';
77
export { query, find, parseSelector } from './query';
88
export {
99
back,

src/snapshot.ts

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,44 @@ import { BrowserEvaluator } from './utils/browser-evaluator';
1111
// Maximum payload size for API requests (10MB server limit)
1212
const MAX_PAYLOAD_BYTES = 10 * 1024 * 1024;
1313

14+
/**
15+
* Structured error for server-side (gateway) snapshot failures.
16+
*
17+
* Keeps HTTP status/URL/response details available to callers for better logging/debugging.
18+
*/
19+
export class SnapshotGatewayError extends Error {
20+
public statusCode?: number;
21+
public url?: string;
22+
public requestId?: string;
23+
public responseText?: string;
24+
public cause?: unknown;
25+
26+
constructor(
27+
message: string,
28+
opts?: {
29+
statusCode?: number;
30+
url?: string;
31+
requestId?: string;
32+
responseText?: string;
33+
cause?: unknown;
34+
}
35+
) {
36+
super(message);
37+
this.name = 'SnapshotGatewayError';
38+
this.statusCode = opts?.statusCode;
39+
this.url = opts?.url;
40+
this.requestId = opts?.requestId;
41+
this.responseText = opts?.responseText;
42+
this.cause = opts?.cause;
43+
}
44+
45+
static snip(s: string | undefined, n: number = 400): string | undefined {
46+
if (!s) return undefined;
47+
const t = String(s).replace(/\r/g, ' ').replace(/\n/g, ' ').trim();
48+
return t.slice(0, n);
49+
}
50+
}
51+
1452
export interface SnapshotOptions {
1553
screenshot?: boolean | { format: 'png' | 'jpeg'; quality?: number };
1654
limit?: number;
@@ -202,6 +240,7 @@ async function snapshotViaApi(
202240
if (!page) {
203241
throw new Error('Browser not started. Call start() first.');
204242
}
243+
const gatewayUrl = `${apiUrl}/v1/snapshot`;
205244

206245
// CRITICAL: Wait for extension injection to complete (CSP-resistant architecture)
207246
// Even for API mode, we need the extension to collect raw data locally
@@ -278,15 +317,38 @@ async function snapshotViaApi(
278317
};
279318

280319
try {
281-
const response = await fetch(`${apiUrl}/v1/snapshot`, {
320+
const response = await fetch(gatewayUrl, {
282321
method: 'POST',
283322
headers,
284323
body: payloadJson,
285324
});
286325

287326
if (!response.ok) {
288-
const errorText = await response.text();
289-
throw new Error(`API request failed: ${response.status} ${errorText}`);
327+
let errorText: string | undefined = undefined;
328+
try {
329+
errorText = await response.text();
330+
} catch (_e) {
331+
errorText = undefined;
332+
}
333+
const requestId =
334+
response.headers.get('x-request-id') || response.headers.get('x-trace-id') || undefined;
335+
const bodySnip = SnapshotGatewayError.snip(errorText);
336+
337+
const parts: string[] = [];
338+
parts.push(`status=${response.status}`);
339+
parts.push(`url=${gatewayUrl}`);
340+
if (requestId) parts.push(`request_id=${requestId}`);
341+
if (bodySnip) parts.push(`body=${bodySnip}`);
342+
343+
throw new SnapshotGatewayError(
344+
`Server-side snapshot API failed: ${parts.join(' ')}. Try using use_api: false to use local extension instead.`,
345+
{
346+
statusCode: response.status,
347+
url: gatewayUrl,
348+
requestId,
349+
responseText: bodySnip,
350+
}
351+
);
290352
}
291353

292354
const apiResult = await response.json();
@@ -359,6 +421,13 @@ async function snapshotViaApi(
359421

360422
return snapshotData;
361423
} catch (e: any) {
362-
throw new Error(`API request failed: ${e.message}`);
424+
if (e instanceof SnapshotGatewayError) {
425+
throw e;
426+
}
427+
const errMsg = e instanceof Error ? `${e.name}: ${e.message}` : String(e);
428+
throw new SnapshotGatewayError(
429+
`Server-side snapshot API failed: url=${gatewayUrl} err=${SnapshotGatewayError.snip(errMsg, 220)}. Try using use_api: false to use local extension instead.`,
430+
{ url: gatewayUrl, cause: e }
431+
);
363432
}
364433
}

0 commit comments

Comments
 (0)