Improve node error handling (#1309)

* Add path mapping and response error interfaces

* Add error handling and throwing functionality

* Refactor error handling into a single function

* Re-implement error handling in Hacker News node

* Fix linting details

* Re-implement error handling in Spotify node

* Re-implement error handling in G Suite Admin node

* 🚧 create basic setup NodeError

* 🚧 add httpCodes

* 🚧 add path priolist

* 🚧 handle statusCode in error, adjust interfaces

* 🚧 fixing type issues w/Ivan

* 🚧 add error exploration

* 👔 fix linter issues

* 🔧 improve object check

* 🚧 remove path passing from NodeApiError

* 🚧 add multi error + refactor findProperty method

* 👔 allow any

* 🔧 handle multi error message callback

*  change return type of callback

*  add customCallback to MultiError

* 🚧 refactor to use INode

* 🔨 handle arrays, continue search after first null property found

* 🚫 refactor method access

* 🚧 setup NodeErrorView

*  change timestamp to Date.now

* 📚 Add documentation for methods and constants

* 🚧 change message setting

* 🚚 move NodeErrors to workflow

*  add new ErrorView for Nodes

* 🎨 improve error notification

* 🎨 refactor interfaces

*  add WorkflowOperationError, refactor error throwing

* 👕 fix linter issues

* 🎨 rename param

* 🐛 fix handling normal errors

*  add usage of NodeApiError

* 🎨 fix throw new error instead of constructor

* 🎨 remove unnecessary code/comments

* 🎨 adjusted spacing + updated status messages

* 🎨 fix tab indentation

*  Replace current errors with custom errors (#1576)

*  Introduce NodeApiError in catch blocks

*  Introduce NodeOperationError in nodes

*  Add missing errors and remove incompatible

*  Fix NodeOperationError in incompatible nodes

* 🔧 Adjust error handling in missed nodes

PayPal, FileMaker, Reddit, Taiga and Facebook Graph API nodes

* 🔨 Adjust Strava Trigger node error handling

* 🔨 Adjust AWS nodes error handling

* 🔨 Remove duplicate instantiation of NodeApiError

* 🐛 fix strava trigger node error handling

* Add XML parsing to NodeApiError constructor (#1633)

* 🐛 Remove type annotation from catch variable

*  Add XML parsing to NodeApiError

*  Simplify error handling in Rekognition node

*  Pass in XML flag in generic functions

* 🔥 Remove try/catch wrappers at call sites

* 🔨 Refactor setting description from XML

* 🔨 Refactor let to const in resource loaders

*  Find property in parsed XML

*  Change let to const

* 🔥 Remove unneeded try/catch block

* 👕 Fix linting issues

* 🐛 Fix errors from merge conflict resolution

*  Add custom errors to latest contributions

* 👕 Fix linting issues

*  Refactor MongoDB helpers for custom errors

* 🐛 Correct custom error type

*  Apply feedback to A nodes

*  Apply feedback to missed A node

*  Apply feedback to B-D nodes

*  Apply feedback to E-F nodes

*  Apply feedback to G nodes

*  Apply feedback to H-L nodes

*  Apply feedback to M nodes

*  Apply feedback to P nodes

*  Apply feedback to R nodes

*  Apply feedback to S nodes

*  Apply feedback to T nodes

*  Apply feedback to V-Z nodes

*  Add HTTP code to iterable node error

* 🔨 Standardize e as error

* 🔨 Standardize err as error

*  Fix error handling for non-standard nodes

Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>

Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
Co-authored-by: Ben Hesseldieck <1849459+BHesseldieck@users.noreply.github.com>
This commit is contained in:
Iván Ovejero
2021-04-16 18:33:36 +02:00
committed by GitHub
parent 1a0e129921
commit 1d27a9e87e
374 changed files with 2041 additions and 2826 deletions

View File

@@ -0,0 +1,177 @@
<template>
<div>
<div class="error-header">
<div class="error-message">ERROR: {{error.message}}</div>
<div class="error-description" v-if="error.description">{{error.description}}</div>
</div>
<details>
<summary class="error-details__summary">
<font-awesome-icon class="error-details__icon" icon="angle-right" /> Details
</summary>
<div class="error-details__content">
<div v-if="error.timestamp">
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix box-card__title">
<span>Time</span>
</div>
<div>
{{new Date(error.timestamp).toLocaleString()}}
</div>
</el-card>
</div>
<div v-if="error.httpCode">
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix box-card__title">
<span>HTTP-Code</span>
</div>
<div>
{{error.httpCode}}
</div>
</el-card>
</div>
<div v-if="error.cause">
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix box-card__title">
<span>Cause</span>
<br>
<span class="box-card__subtitle">Data below may contain sensitive information. Proceed with caution when sharing.</span>
</div>
<div>
<el-button class="copy-button" @click="copyCause" circle type="text" title="Copy to clipboard">
<font-awesome-icon icon="copy" />
</el-button>
<vue-json-pretty
:data="error.cause"
:deep="3"
:showLength="true"
selectableType="single"
path="error"
class="json-data"
/>
</div>
</el-card>
</div>
<div v-if="error.stack">
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix box-card__title">
<span>Stack</span>
</div>
<div>
<pre><code>{{error.stack}}</code></pre>
</div>
</el-card>
</div>
</div>
</details>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
//@ts-ignore
import VueJsonPretty from 'vue-json-pretty';
import { copyPaste } from '@/components/mixins/copyPaste';
import { showMessage } from '@/components/mixins/showMessage';
import mixins from 'vue-typed-mixins';
export default mixins(
copyPaste,
showMessage,
).extend({
name: 'NodeErrorView',
props: [
'error',
],
components: {
VueJsonPretty,
},
methods: {
copyCause() {
this.copyToClipboard(JSON.stringify(this.error.cause));
this.copySuccess();
},
copySuccess() {
this.$showMessage({
title: 'Copied to clipboard',
message: '',
type: 'info',
});
},
},
});
</script>
<style lang="scss">
.error-header {
margin-bottom: 10px;
}
.error-message {
color: #ff0000;
font-weight: bold;
font-size: 1.1rem;
}
.error-description {
margin-top: 10px;
font-size: 1rem;
}
.error-details__summary {
font-weight: 600;
font-size: 16px;
cursor: pointer;
outline:none;
}
.error-details__icon {
margin-right: 4px;
}
details > summary {
list-style-type: none;
}
details > summary::-webkit-details-marker {
display: none;
}
details[open] {
.error-details__icon {
transform: rotate(90deg);
}
}
.error-details__content {
margin-top: 15px;
}
.el-divider__text {
background-color: #f9f9f9;
}
.box-card {
margin-top: 1em;
overflow: auto;
}
.box-card__title {
font-weight: 400;
}
.box-card__subtitle {
font-weight: 200;
font-style: italic;
font-size: 0.7rem;
}
.copy-button {
position: absolute;
font-size: 1.1rem;
right: 50px;
z-index: 1000;
}
</style>

View File

@@ -81,8 +81,7 @@
<div class="data-display-content">
<span v-if="node && workflowRunData !== null && workflowRunData.hasOwnProperty(node.name)">
<div v-if="workflowRunData[node.name][runIndex].error" class="error-display">
<div class="error-message">ERROR: {{workflowRunData[node.name][runIndex].error.message}}</div>
<pre><code>{{workflowRunData[node.name][runIndex].error.stack}}</code></pre>
<NodeErrorView :error="workflowRunData[node.name][runIndex].error" />
</div>
<span v-else>
<div v-if="showData === false" class="to-much-data">
@@ -226,6 +225,7 @@ import {
} from '@/constants';
import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
import NodeErrorView from '@/components/Error/NodeViewError.vue';
import { copyPaste } from '@/components/mixins/copyPaste';
import { genericHelpers } from '@/components/mixins/genericHelpers';
@@ -247,6 +247,7 @@ export default mixins(
name: 'RunData',
components: {
BinaryDataDisplay,
NodeErrorView,
VueJsonPretty,
},
data () {
@@ -739,13 +740,6 @@ export default mixins(
}
}
.error-display {
.error-message {
color: #ff0000;
font-weight: bold;
}
}
table {
border-collapse: collapse;
text-align: left;

View File

@@ -207,8 +207,19 @@ export const pushConnection = mixins(
if (runDataExecuted.finished !== true) {
// There was a problem with executing the workflow
let errorMessage = 'There was a problem executing the workflow!';
if (runDataExecuted.data.resultData.error && runDataExecuted.data.resultData.error.message) {
errorMessage = `There was a problem executing the workflow:<br /><strong>"${runDataExecuted.data.resultData.error.message}"</strong>`;
let nodeName: string | undefined;
if (runDataExecuted.data.resultData.error.node) {
nodeName = typeof runDataExecuted.data.resultData.error.node === 'string'
? runDataExecuted.data.resultData.error.node
: runDataExecuted.data.resultData.error.node.name;
}
const receivedError = nodeName
? `${nodeName}: ${runDataExecuted.data.resultData.error.message}`
: runDataExecuted.data.resultData.error.message;
errorMessage = `There was a problem executing the workflow:<br /><strong>"${receivedError}"</strong>`;
}
this.$titleSet(workflow.name, 'ERROR');
this.$showMessage({

View File

@@ -459,6 +459,10 @@ h1, h2, h3, h4, h5, h6 {
border: none;
}
.el-notification__content {
text-align: left;
}
// Custom scrollbar
::-webkit-scrollbar {