Skip to content

Conversation

@cehan-Chloe
Copy link
Contributor

@cehan-Chloe cehan-Chloe commented Dec 22, 2025

When an error occurs in a state, ErrorController tries in order:

  • Node-level errorState transition - Most specific, handles errors for this state only
  • Flow-level errorState - General fallback, handles errors from any state in flow
  • Reject flow promise - No error handling defined
    Error with no node/flow errorState → flowResultDeferred.reject(error)

detail doc: 4481c71

Change Type (required)

Indicate the type of change your pull request is:

  • patch
  • minor
  • major
  • N/A

Does your PR have any documentation updates?

  • Updated docs
  • No Update needed
  • Unable to update docs

@codecov
Copy link

codecov bot commented Dec 22, 2025

Bundle Report

Changes will increase total bundle size by 28.59kB (0.5%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
plugins/async-node/core 470.66kB 1.78kB (0.38%) ⬆️
plugins/beacon/core 417.89kB 1.78kB (0.43%) ⬆️
core/player* 1.0MB 12.54kB (1.27%) ⬆️
plugins/check-path/core 436.29kB 1.78kB (0.41%) ⬆️
plugins/common-expressions/core 422.14kB 1.78kB (0.42%) ⬆️
plugins/common-types/core 496.47kB 1.78kB (0.36%) ⬆️
plugins/markdown/core 676.96kB 1.78kB (0.26%) ⬆️
plugins/metrics/core 454.45kB 1.78kB (0.39%) ⬆️
plugins/stage-revert-data/core 399.91kB 1.78kB (0.45%) ⬆️
plugins/reference-assets/core 477.6kB 1.78kB (0.37%) ⬆️

ℹ️ *Bundle size includes cached data from a previous commit

Affected Assets, Files, and Routes:

view changes for bundle: core/player

Assets Changed:

Asset Name Size Change Total Size Change (%)
Player.native.js 2.31kB 419.65kB 0.55%
cjs/index.cjs 3.46kB 198.33kB 1.78%
index.legacy-esm.js 3.39kB 191.66kB 1.8%
index.mjs 3.39kB 191.66kB 1.8%
view changes for bundle: plugins/beacon/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
BeaconPlugin.native.js 1.78kB 403.42kB 0.44%
view changes for bundle: plugins/metrics/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
MetricsPlugin.native.js 1.78kB 422.1kB 0.42%
view changes for bundle: plugins/reference-assets/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
ReferenceAssetsPlugin.native.js 1.78kB 447.7kB 0.4%
view changes for bundle: plugins/async-node/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
AsyncNodePlugin.native.js 1.78kB 424.58kB 0.42%
view changes for bundle: plugins/common-expressions/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
CommonExpressionsPlugin.native.js 1.78kB 400.9kB 0.45%
view changes for bundle: plugins/stage-revert-data/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
StageRevertDataPlugin.native.js 1.78kB 393.08kB 0.46%
view changes for bundle: plugins/common-types/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
CommonTypesPlugin.native.js 1.78kB 425.3kB 0.42%
view changes for bundle: plugins/check-path/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
CheckPathPlugin.native.js 1.78kB 406.8kB 0.44%
view changes for bundle: plugins/markdown/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
MarkdownPlugin.native.js 1.78kB 651.81kB 0.27%

@codecov
Copy link

codecov bot commented Dec 22, 2025

Codecov Report

❌ Patch coverage is 92.45283% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.87%. Comparing base (4481c71) to head (d274059).
⚠️ Report is 3 commits behind head on error-controller.

Files with missing lines Patch % Lines
core/player/src/controllers/error/utils.ts 84.21% 3 Missing ⚠️
core/player/src/controllers/flow/flow.ts 85.00% 3 Missing ⚠️
core/player/src/controllers/error/controller.ts 96.72% 2 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                  @@
##           error-controller     #775      +/-   ##
====================================================
+ Coverage             85.84%   85.87%   +0.02%     
====================================================
  Files                   508      509       +1     
  Lines                 22892    22980      +88     
  Branches               2673     2696      +23     
====================================================
+ Hits                  19652    19734      +82     
- Misses                 2911     2917       +6     
  Partials                329      329              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cehan-Chloe cehan-Chloe marked this pull request as ready for review January 8, 2026 15:36
@cehan-Chloe cehan-Chloe requested a review from a team as a code owner January 8, 2026 15:36
Comment on lines 241 to 242
if (typeof errorState === "object" && errorState !== null) {
const dict = errorState as Record<string, string>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Pulling the check into a type assertion function removes the need to cast after checking here. As well, for real type safety you also need to check !Array.isArray(errorState) since arrays are also object types.

export const isRecord = (
  obj: unknown
): obj is Record<PropertyKey, unknown> =>
  typeof obj === "object" && obj !== null && !Array.isArray(obj);

This example has the values of the record as unknown which would require you to type check those too. You could add a generic to pre-determine the record value type to skip that step but it is technically more error-prone:

export const isRecord = <T>(
  obj: unknown
): obj is Record<PropertyKey, T> => ...

Comment on lines 267 to 269
const nodeErrorStateConfig = currentState?.value.errorState as
| ErrorStateTransition
| undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we need to type cast here? Do not all navigation states support an errorState?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The errorState is optional for both flow and node level. Also for some states like end state, errorState may not be needed

Comment on lines 276 to 281
errorController.setOptions({
model: dataController,
logger: this.logger,
flow: flowController,
fail: flowResultDeferred.reject,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Could some of the properties here just be moved to the constructor so you don't need null checks and fallbacks for everything? Seems like only the dataController isn't available when this is constructed.

Comment on lines 169 to 176
let errorStateName: string | undefined;

if (typeof errorStateConfig === "string") {
errorStateName = errorStateConfig;
} else {
errorStateName =
(errorType && errorStateConfig[errorType]) || errorStateConfig["*"];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems pretty similar to the error controller's resolveErrorState. Could we pull that out into a shared util?

* @param errorType Optional error type for dictionary-based error transition
* @returns true if navigation succeeded, false if errorState not defined or navigation failed
*/
public transitionToErrorState(errorType?: string): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this function? Couldn't we just use the existing transition function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For node level, I still use the existing transition function. This is the flow-level error we don't have transitions map, so I use error type as the key. Do you think it's better to have consistency between flow and node? I can add transitions to flow level.
samples:
flow:

"errorState": {
    "network": "NETWORK_ERROR_VIEW",
  }

node:

    "SHIPPING_VIEW": {
      "state_type": "VIEW",
      "ref": "shipping-form",
      "errorState": "node-error",
      "transitions": {
        "node-error": "NODE_ERROR_VIEW"
      }
    },

Copy link
Member

Choose a reason for hiding this comment

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

I think so. Also if we can centralize some of the logic here and in navigateToErrorState and make them more utility oriented I think it might be cleaner long term as that logic needs to evolve

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.

4 participants