diff --git a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index 73e031e52e..3275938759 100644 --- a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -63,6 +63,7 @@ interface IResourceLocatorQuery { message?: string; description?: string; httpCode?: string; + stackTrace?: string; }; loading: boolean; } @@ -154,9 +155,26 @@ const selectedMode = computed(() => { const isListMode = computed(() => selectedMode.value === 'list'); -const hasPermissionError = computed(() => - ['401', '403'].includes(currentResponse.value?.errorDetails?.httpCode ?? ''), -); +const hasCredentialError = computed(() => { + const PERMISSION_ERROR_CODES = ['401', '403']; + // Some of our NodeAPIErrors just return 500 without any details, + // so checking messages and stack traces for permission errors + const NODE_API_AUTH_ERROR_MESSAGES = [ + 'NodeApiError: Authorization failed', + 'NodeApiError: Unable to sign without access token', + 'secretOrPrivateKey must be an asymmetric key when using RS256', + ]; + // Check if error stack trace contains permission error messages + const stackTraceContainsCredentialError = (currentResponse.value?.errorDetails?.stackTrace ?? '') + .split('\n') + .some((line) => NODE_API_AUTH_ERROR_MESSAGES.includes(line.trim())); + + return ( + PERMISSION_ERROR_CODES.includes(currentResponse.value?.errorDetails?.httpCode ?? '') || + NODE_API_AUTH_ERROR_MESSAGES.includes(currentResponse.value?.errorDetails?.message ?? '') || + stackTraceContainsCredentialError + ); +}); const credentialsNotSet = computed(() => { if (!props.node) return false; @@ -784,28 +802,31 @@ function removeOverride() { @load-more="loadResourcesDebounced" >