Skip to content

Commit 7ed5df9

Browse files
committed
Improve error UX around interception activation API
1 parent 8683d67 commit 7ed5df9

File tree

5 files changed

+30
-18
lines changed

5 files changed

+30
-18
lines changed

src/api/api-model.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,17 @@ export class ApiModel {
189189
} catch (err: any) {
190190
const activationError = err as ActivationError;
191191
activationDone = true;
192+
192193
if (activationError.reportable !== false) {
193194
addBreadcrumb(`Failed to activate ${id}`, { category: 'interceptor' });
194-
logError(err);
195+
throw err;
195196
}
197+
198+
// Non-reportable errors are friendly ones (like Global Chrome quit confirmation)
199+
// that need to be returned nicely to the UI for further processing.
196200
return {
197201
success: false,
198-
metadata: activationError.metadata,
199-
error: activationError.reportable !== false
200-
? serializeError(activationError)
201-
: false
202+
metadata: activationError.metadata
202203
};
203204
}
204205
}

src/api/rest-api.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,10 @@ export function exposeRestAPI(
8989
const interceptorOptions = req.body;
9090
const result = await apiModel.activateInterceptor(interceptorId, proxyPort, interceptorOptions);
9191

92-
if (result.success === true || result.error === false) {
93-
// Some non-success is just temporary, e.g. global Chrome "exit running app please" confirmation.
94-
res.json({ result });
95-
} else {
96-
res.status(500).json({ result });
97-
}
92+
// No thrown error here doesn't mean success: we have non-reportable failures for cases like
93+
// Global Chrome "prompt to confirm quit" errors. We return those as 200 { success: false, metadata: ... }
94+
95+
res.json({ result });
9896
}));
9997

10098
server.post('/client/send', handleErrors(async (req, res) => {

src/interceptors/frida/frida-android-integration.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ export async function launchAndroidHost(adbClient: AdbClient, hostId: string) {
130130
const runAsRoot = await getRootCommand(deviceClient);
131131

132132
if (!runAsRoot) {
133-
throw new Error("Couldn't get root access to launch Frida Server");
133+
throw new CustomError("Couldn't get root access to launch Frida Server", {
134+
code: 'no-root'
135+
});
134136
}
135137

136138
const fridaServerStream = await deviceClient.shell(
@@ -151,7 +153,7 @@ export async function launchAndroidHost(adbClient: AdbClient, hostId: string) {
151153

152154
return fridaServerStream;
153155
} catch (e: any) {
154-
const errorMessage = e?.message === 'Wait loop failed'
156+
const errorMessage = e?.code === 'wait-loop-failed'
155157
? 'Frida server did not startup before timeout'
156158
: e.message ?? e;
157159
console.log('Fride launch failed:', errorMessage);
@@ -165,7 +167,7 @@ export async function launchAndroidHost(adbClient: AdbClient, hostId: string) {
165167
);
166168
});
167169

168-
throw new Error(`Failed to launch Frida server for ${hostId}: ${e.message ?? e}`);
170+
throw new CustomError(errorMessage, { code: e?.code, cause: e });
169171
}
170172
}
171173

src/interceptors/frida/frida-integration.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ class FridaScriptError extends CustomError {
7171
constructor(
7272
message: FridaJs.ScriptAgentErrorMessage
7373
) {
74-
super(message.description);
74+
super(message.description, {
75+
code: 'frida-script-error'
76+
});
7577
if (message.stack) {
7678
this.stack = message.stack;
7779
}
@@ -121,7 +123,7 @@ export async function testAndSelectProxyAddress(
121123
if (message.payload.type === 'connected') {
122124
resolve(message.payload.ip as string);
123125
} else if (message.payload.type === 'connection-failed') {
124-
reject(new Error(`Could not connect to proxy on port ${proxyPort} at ${
126+
reject(new FridaProxyError(`Could not connect to proxy on port ${proxyPort} at ${
125127
ips.length > 1
126128
? `any of: ${ips.join(', ')}`
127129
: ips[0]
@@ -143,7 +145,12 @@ export async function testAndSelectProxyAddress(
143145
reject(e);
144146
}
145147
})).catch((e) => {
146-
throw new FridaProxyError("No proxy IPs were reachable from the target", { cause: e });
148+
if (e instanceof FridaProxyError) throw e;
149+
else {
150+
throw new FridaProxyError(`Proxy IP detection on target device failed for port ${proxyPort} and IPs ${
151+
JSON.stringify(ips)
152+
}`, { cause: e });
153+
}
147154
});
148155
}
149156

src/util/promise.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ export async function waitUntil<T extends unknown>(
1313
result = await test();
1414
}
1515

16-
if (!result) throw new Error(`Wait loop failed`);
16+
if (!result) {
17+
throw new CustomError(`Wait loop failed after ${tries} retries`, {
18+
code: 'wait-loop-failed'
19+
});
20+
}
1721
else return result as Exclude<T, false>;
1822
}
1923

0 commit comments

Comments
 (0)