Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue3: Exceptions thrown in data result in blank page #11807

Open
richard-cox opened this issue Sep 4, 2024 · 4 comments · May be fixed by #12198
Open

Vue3: Exceptions thrown in data result in blank page #11807

richard-cox opened this issue Sep 4, 2024 · 4 comments · May be fixed by #12198
Assignees
Labels
area/vue3 Bugs and technical debts as outcome to the Vue3 migration kind/bug QA/dev-automation Issues that engineers have written automation around so QA doesn't have look at this
Milestone

Comments

@richard-cox
Copy link
Member

richard-cox commented Sep 4, 2024

Setup

  • Rancher version: dev of 2.10.0

Describe the bug

  • Exception in data function breaks dashboard
  • Page shown contents no content at all
  • This is a regression from 2.9, exposing us to cases where exceptions are swallowed

To Reproduce

  • Artificially manufacture an error in a component's data function, for example
    • for example /shell/pages/home.vue
    • data() {
        throw new Error('sdfdsf');
      },
      
  • Visit dashboard home page

Result

  • Completely blank page

Expected Result

  • Basics of page rendered
  • image

Additional Information

  • Exceptions throw in the following behave the same as previously
    • fetch
    • computed property
    • created
@richard-cox richard-cox added kind/bug area/vue3 Bugs and technical debts as outcome to the Vue3 migration labels Sep 4, 2024
@richard-cox richard-cox added this to the v2.10.0 milestone Sep 4, 2024
@github-actions github-actions bot added the QA/dev-automation Issues that engineers have written automation around so QA doesn't have look at this label Sep 4, 2024
@richard-cox richard-cox changed the title Exceptions thrown in data result in blank page Vue3: Exceptions thrown in data result in blank page Sep 4, 2024
@eva-vashkevich eva-vashkevich linked a pull request Oct 9, 2024 that will close this issue
7 tasks
@eva-vashkevich
Copy link
Member

We are pushing this issue out because it appears to be more complex than originally thought. A few discoveries:

  • Vue 3 doesn't seem to catch errors in data like Vue 2 did. Internal data handling is missing error handling which doesn't let us just carry on like Vue2 did.
  • vueApp.config.errorHandler is only configured for dev environment. This results in a blank page in production. We should add some error handling for non-dev setup.
  • Adding ErrorBound doesn't seem to catch the error, but it can be worked around by using try-catch inside data.
  • If you try to go to a page that throws error in data, it might cause a Vue error. This gets app in a weird state. We should come up with a repro and submit a bug report to Vue. Refreshing the page redirects the page to fail-whale like it should.
"[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core 
  at <Index class="outlet" onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouterView key="/c/_/manager/cloudCredential" class="outlet" > 
  at <Default onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy(Object) {_fetchDelay: 200, $fetch: ƒ, updatePageActions: ƒ, setCustomColor: ƒ, removeCustomColor: ƒ, …} > > 
  at <RouterView key=1 > 
  at <App>"

This can be reproduced by throwing an error inside data in 'shell/pages/c/_cluster/manager/cloudCredential/index.vue'

Some suggestions: #12198

@eva-vashkevich eva-vashkevich modified the milestones: v2.10.0, v2.11.0 Oct 9, 2024
@rak-phillip
Copy link
Member

We should strongly consider refactoring instances of data that contain complex initialization logic. The project will benefit from writing idiomatic Vue code, and my concern is that we're trying to preserve an anti-pattern instead of correcting and discouraging its usage.

We can eliminate this problem entirely by moving logic and side effects to lifecycle hooks, computed props, or methods and keeping data simple and focused on initializing reactive state.

@richard-cox
Copy link
Member Author

@rak-phillip If the anti-pattern was just tech debt i would agree. This issue though is about ensuring the ui doesn't 'crash' (show a blank page, require refresh), which is about worst thing that can happen, erodes faith in the product and rancher, and is a vue3 UX regression.

Once we identify places where this covers we can address in a better, targeted way (whilst still incrementally converting the complex data fn's over to something better).

@rak-phillip
Copy link
Member

rak-phillip commented Oct 11, 2024

In that case, I'd like to advocate for guarding against as many critical failures as possible for 2.10.

A straightforward way to address this is to wrap each offending instance of complex initialization in data in a try..catch block, handle the error ourselves, and allow Vue to return some data object (closer to the Vue2 behavior). It's not elegant, but it limits the scope for potential failures and erosion of trust.

If we consider all components that contain a data prop that does not immediately return an object

data () {
  return {

These can be interpreted as containing complex initialization logic; we would have at least 155 components to cover:

grep -rPzol -C 5 "data\s*\(\)\s*{(?![^{]*return\s*{)" --exclude-dir node_modules --include="*.vue" .

./pkg/aks/components/Taint.vue
./pkg/harvester-manager/machine-config/harvester.vue
./shell/chart/monitoring/grafana/index.vue
./shell/chart/istio.vue
./shell/cloud-credential/generic.vue
./shell/cloud-credential/azure.vue
./shell/components/EmberPageView.vue
./shell/components/Questions/Reference.vue
./shell/components/ResourceList/Masthead.vue
./shell/components/ResourceList/index.vue
./shell/components/SortableTable/index.vue
./shell/components/fleet/FleetIntro.vue
./shell/components/fleet/FleetNoWorkspaces.vue
./shell/components/form/ResourceQuota/Project.vue
./shell/components/form/Command.vue
./shell/components/form/EnvVars.vue
./shell/components/form/HealthCheck.vue
./shell/components/form/HookOption.vue
./shell/components/form/LifecycleHooks.vue
./shell/components/form/MatchExpressions.vue
./shell/components/form/NameNsDescription.vue
./shell/components/form/Networking.vue
./shell/components/form/NodeAffinity.vue
./shell/components/form/NodeScheduling.vue
./shell/components/form/PodAffinity.vue
./shell/components/form/Probe.vue
./shell/components/form/ResourceSelector.vue
./shell/components/form/ShellInput.vue
./shell/components/form/Tolerations.vue
./shell/components/form/ValueFromResource.vue
./shell/components/form/WorkloadPorts.vue
./shell/components/form/ArrayList.vue
./shell/components/form/Security.vue
./shell/components/formatter/ExtensionCache.vue
./shell/components/formatter/Port.vue
./shell/components/formatter/SecretData.vue
./shell/components/formatter/SecretType.vue
./shell/components/formatter/ServiceType.vue
./shell/components/nav/TopLevelMenu.vue
./shell/components/AlertTable.vue
./shell/components/ContainerResourceLimit.vue
./shell/components/HarvesterServiceAddOnConfig.vue
./shell/components/PromptRemove.vue
./shell/components/ResourceYaml.vue
./shell/components/YamlEditor.vue
./shell/detail/management.cattle.io.user.vue
./shell/detail/namespace.vue
./shell/detail/secret.vue
./shell/detail/service.vue
./shell/edit/auth/ldap/config.vue
./shell/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue
./shell/edit/autoscaling.horizontalpodautoscaler/metric-target.vue
./shell/edit/constraints.gatekeeper.sh.constraint/index.vue
./shell/edit/logging-flow/index.vue
./shell/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue
./shell/edit/logging.banzaicloud.io.output/providers/gelf.vue
./shell/edit/logging.banzaicloud.io.output/providers/opensearch.vue
./shell/edit/logging.banzaicloud.io.output/providers/redis.vue
./shell/edit/logging.banzaicloud.io.output/providers/syslog.vue
./shell/edit/logging.banzaicloud.io.output/index.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/auth.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/index.vue
./shell/edit/monitoring.coreos.com.alertmanagerconfig/tls.vue
./shell/edit/monitoring.coreos.com.receiver/types/opsgenie.vue
./shell/edit/monitoring.coreos.com.receiver/types/pagerduty.vue
./shell/edit/monitoring.coreos.com.receiver/types/slack.vue
./shell/edit/monitoring.coreos.com.receiver/types/webhook.vue
./shell/edit/monitoring.coreos.com.receiver/auth.vue
./shell/edit/monitoring.coreos.com.receiver/index.vue
./shell/edit/monitoring.coreos.com.receiver/tls.vue
./shell/edit/networking.istio.io.destinationrule/LoadBalancer.vue
./shell/edit/networking.k8s.io.ingress/Certificate.vue
./shell/edit/networking.k8s.io.ingress/Rule.vue
./shell/edit/networking.k8s.io.ingress/RulePath.vue
./shell/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue
./shell/edit/networking.k8s.io.networkpolicy/PolicyRules.vue
./shell/edit/networking.k8s.io.networkpolicy/index.vue
./shell/edit/persistentvolume/plugins/awsElasticBlockStore.vue
./shell/edit/persistentvolume/plugins/azureDisk.vue
./shell/edit/persistentvolume/plugins/azureFile.vue
./shell/edit/persistentvolume/plugins/cephfs.vue
./shell/edit/persistentvolume/plugins/cinder.vue
./shell/edit/persistentvolume/plugins/csi.vue
./shell/edit/persistentvolume/plugins/fc.vue
./shell/edit/persistentvolume/plugins/flexVolume.vue
./shell/edit/persistentvolume/plugins/flocker.vue
./shell/edit/persistentvolume/plugins/gcePersistentDisk.vue
./shell/edit/persistentvolume/plugins/glusterfs.vue
./shell/edit/persistentvolume/plugins/hostPath.vue
./shell/edit/persistentvolume/plugins/iscsi.vue
./shell/edit/persistentvolume/plugins/local.vue
./shell/edit/persistentvolume/plugins/longhorn.vue
./shell/edit/persistentvolume/plugins/nfs.vue
./shell/edit/persistentvolume/plugins/photonPersistentDisk.vue
./shell/edit/persistentvolume/plugins/portworxVolume.vue
./shell/edit/persistentvolume/plugins/quobyte.vue
./shell/edit/persistentvolume/plugins/rbd.vue
./shell/edit/persistentvolume/plugins/scaleIO.vue
./shell/edit/persistentvolume/plugins/storageos.vue
./shell/edit/persistentvolume/plugins/vsphereVolume.vue
./shell/edit/persistentvolume/index.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue
./shell/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue
./shell/edit/provisioning.cattle.io.cluster/rke2.vue
./shell/edit/secret/index.vue
./shell/edit/secret/registry.vue
./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/aws-ebs.vue
./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/azure-disk.vue
./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/gce-pd.vue
./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/vsphere-volume.vue
./shell/edit/storage.k8s.io.storageclass/provisioners/driver.longhorn.io.vue
./shell/edit/storage.k8s.io.storageclass/index.vue
./shell/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue
./shell/edit/workload/Job.vue
./shell/edit/workload/Upgrading.vue
./shell/edit/cis.cattle.io.clusterscanbenchmark.vue
./shell/edit/cis.cattle.io.clusterscanprofile.vue
./shell/edit/configmap.vue
./shell/edit/fleet.cattle.io.gitrepo.vue
./shell/edit/helm.cattle.io.projecthelmchart.vue
./shell/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue
./shell/edit/management.cattle.io.fleetworkspace.vue
./shell/edit/management.cattle.io.project.vue
./shell/edit/namespace.vue
./shell/edit/persistentvolumeclaim.vue
./shell/edit/policy.poddisruptionbudget.vue
./shell/edit/resources.cattle.io.restore.vue
./shell/edit/service.vue
./shell/edit/token.vue
./shell/edit/resources.cattle.io.backup.vue
./shell/list/workload.vue
./shell/machine-config/digitalocean.vue
./shell/machine-config/vmwarevsphere.vue
./shell/pages/auth/login.vue
./shell/pages/auth/verify.vue
./shell/pages/c/_cluster/apps/charts/install.vue
./shell/pages/c/_cluster/auth/config/index.vue
./shell/pages/c/_cluster/explorer/EventsTable.vue
./shell/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue
./shell/pages/c/_cluster/monitoring/monitor/create.vue
./shell/pages/c/_cluster/monitoring/route-receiver/_id.vue
./shell/pages/c/_cluster/monitoring/route-receiver/create.vue
./shell/pages/c/_cluster/uiplugins/CatalogList/index.vue
./shell/pages/diagnostic.vue
./shell/pages/fail-whale.vue
./shell/pages/home.vue

We can also use this list as potential candidates for refactoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/vue3 Bugs and technical debts as outcome to the Vue3 migration kind/bug QA/dev-automation Issues that engineers have written automation around so QA doesn't have look at this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants