Skip to content

refactor: new client error structure#7

Merged
dkales merged 4 commits intomainfrom
dk/client_error
Mar 9, 2026
Merged

refactor: new client error structure#7
dkales merged 4 commits intomainfrom
dk/client_error

Conversation

@dkales
Copy link
Member

@dkales dkales commented Mar 9, 2026

Note

Medium Risk
Medium risk because it changes public API signatures (distributedOprf/initSessions) and overhauls error propagation/handling paths across WebSocket and session management.

Overview
Refactors @taceo/oprf-client to take pre-built WebSocket service URLs instead of {baseUrl,module,protocolVersion} parameters, adding toOprfUri to construct endpoints and updating the example CLI + README usage accordingly.

Introduces a two-tier error model (NodeError/ServiceError vs OprfClientError) and new aggregateError(threshold, errors) logic, with initSessions now throwing NodeError[] on threshold failure and distributedOprf translating those into protocol-level errors (plus a dedicated CannotFinishSession wrapper). Tests are updated to cover the new URI builder and error aggregation behavior.

Written by Cursor Bugbot for commit 881eb9e. This will update automatically on new commits. Configure here.

@dkales dkales requested a review from 0xThemis March 9, 2026 13:40
{ errors: Object.fromEntries(errors) }
);
// Not enough responses — throw collected node errors for caller to aggregate
throw nodeErrors;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty nodeErrors array causes misleading error on epoch disagreement

Medium Severity

When all WebSocket connections succeed but no single epoch reaches the threshold (e.g., 3 services each returning a different epoch with threshold 2), nodeErrors is empty and throw nodeErrors throws []. In distributedOprf, [].every(isNodeError) is vacuously true, so aggregateError(threshold, []) is called with an empty array. This falls through all aggregation checks and returns a NodeErrorDisagreement with the message "Nodes returned disagreeing errors" and an empty nodeErrors detail — even though no nodes actually errored. The real cause (epoch disagreement) is completely lost.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

} catch (err) {
// initSessions throws NodeError[] on threshold failure
if (Array.isArray(err) && err.every(isNodeError)) {
throw aggregateError(threshold, err as NodeError[]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty error array causes misleading aggregation result

Medium Severity

When all WebSocket connections succeed but no epoch bucket reaches threshold (e.g., all nodes are on different epochs), initSessions throws an empty NodeError[]. In distributedOprf, the guard err.every(isNodeError) is vacuously true for empty arrays, so aggregateError(threshold, []) is called. This produces a misleading NodeErrorDisagreement with zero nodeErrors and the message "Nodes returned disagreeing errors" — when the real issue is epoch disagreement, not node errors.

Additional Locations (1)

Fix in Cursor Fix in Web

@dkales dkales merged commit f0e5971 into main Mar 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants