Migrate top-20 high-frequency catch sites to AppError taxonomy (C6.1 part 2/2)

Each of these catches already logged via an accessible `logger` or `log`.
The migration wraps the thrown value through `classifyUnknownError(raw,
fallback)` and emits the log line with the structured `[code]` prefix.
Observable behaviour — return values, fail strings, DB writes — is
unchanged; the only addition is a machine-readable `code` on every log
line so future telemetry can bucket by category.

Sites migrated (11 files, 20 catch sites):

  src/main/browser-action-service.ts             (2) approval lookup, payload JSON
  src/main/ipc-credentials-handlers.ts           (4) save, remove, test lookup, test resolve
  src/main/hire-hook.ts                          (3) getAgent, connector def, outer exception
  src/main/checkpoint-engine.ts                  (2) onTaskStarted, onDocumentDrafted
  src/main/document-lifecycle.ts                 (1) getRun while deriving taskId
  src/main/skills/runtime.ts                     (2) builtin statSync, builtin readdir
  src/main/worker/handlers/run-status-handler.ts (1) run not found during status
  src/main/worker/handlers/run-log-handler.ts    (1) lease renewal lookup
  src/main/notification-service.ts               (1) notification.close during destroy
  src/main/updater-service.ts                    (1) autoUpdater.checkForUpdates
  src/main/ipc-support.ts                        (2) ipc handler throw, emitEvent send

Why only 20 tonight: 248 catches exist in src/main/. Rewriting them all
in one commit is high-diff-risk (collides with Linus's in-flight
database/backup/migration work on database/*, connector-definitions-*,
message-* and scripts/*) and low-value (pure-library catches with no
accessible logger produce dead `void classified` constructs). The
taxonomy module is committed separately so the remaining 228 sites can
land incrementally via the C6.2 proposal.

All 11 files selected sit outside Linus's working set. Verified:
  - pnpm typecheck   clean
  - pnpm test:unit   498 passed
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 12:22:52 -04:00
1 parent d7e267031f
commit 0db6e4261f
15 files changed
+204 -29

No files matched your search

+29 -4
View File
@@ -15,6 +15,7 @@ import type { CredentialResolver } from "./credentials/credential-resolver";
import type { CredentialStore } from "./credentials/credential-store";
import type { StoredCredentialPayload } from "./credentials/types";
import { ok } from "./ipc-core-common";
import { classifyUnknownError } from "./errors/index.js";
/** Strip credential-shaped substrings from an error message before sending it
* back to the renderer. Matches are anchored to issuer-specific prefixes so
@@ -104,7 +105,13 @@ export function registerCredentialIpcHandlers(deps: CredentialHandlerDeps): () =
deps.emitEvent({ type: "credentials-changed", connectorId: parsed.data.connectorId });
return ok<CredentialSummary>(stored);
} catch (error) {
deps.logger.error(`[credentials] save failed for ${parsed.data.connectorId}: ${describeError(error)}`);
const err = classifyUnknownError(error, {
kind: "upstream",
code: "credentials.save.failed",
message: `save failed for ${parsed.data.connectorId}`,
context: { connectorId: parsed.data.connectorId },
});
deps.logger.error(`[${err.code}] ${err.message}: ${describeError(error)}`);
return deps.fail("SAVE_FAILED", "Could not save credential. Check application logs for details.");
}
});
@@ -118,7 +125,13 @@ export function registerCredentialIpcHandlers(deps: CredentialHandlerDeps): () =
deps.emitEvent({ type: "credentials-changed", connectorId: parsed.data.connectorId });
return ok(true);
} catch (error) {
deps.logger.error(`[credentials] remove failed for ${parsed.data.connectorId}: ${describeError(error)}`);
const err = classifyUnknownError(error, {
kind: "upstream",
code: "credentials.remove.failed",
message: `remove failed for ${parsed.data.connectorId}`,
context: { connectorId: parsed.data.connectorId },
});
deps.logger.error(`[${err.code}] ${err.message}: ${describeError(error)}`);
return deps.fail("REMOVE_FAILED", "Could not remove credential. Check application logs for details.");
}
});
@@ -130,15 +143,27 @@ export function registerCredentialIpcHandlers(deps: CredentialHandlerDeps): () =
try {
definition = getConnectorDefinition(parsed.data.connectorId);
} catch (error) {
deps.logger.error(`[credentials] test failed lookup for ${parsed.data.connectorId}: ${describeError(error)}`);
const err = classifyUnknownError(error, {
kind: "user_input",
code: "credentials.test.unknown_connector",
message: `test failed lookup for ${parsed.data.connectorId}`,
context: { connectorId: parsed.data.connectorId },
});
deps.logger.error(`[${err.code}] ${err.message}: ${describeError(error)}`);
return deps.fail("UNKNOWN_CONNECTOR", "Unknown connector.");
}
let resolved;
try {
resolved = await deps.resolver.resolve(parsed.data.connectorId);
} catch (error) {
const err = classifyUnknownError(error, {
kind: "upstream",
code: "credentials.test.resolve_failed",
message: `test resolve failed for ${parsed.data.connectorId}`,
context: { connectorId: parsed.data.connectorId },
});
const message = describeError(error);
deps.logger.error(`[credentials] test resolve failed for ${parsed.data.connectorId}: ${message}`);
deps.logger.error(`[${err.code}] ${err.message}: ${message}`);
return ok({ ok: false, message: redactSecrets(message) });
}