diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx
index 16107a6cc0..549c4569cf 100644
--- a/packages/app/src/components/catalog/EntityPage.tsx
+++ b/packages/app/src/components/catalog/EntityPage.tsx
@@ -40,6 +40,8 @@ import {
isKind,
EntityHasResourcesCard,
EntityOrphanWarning,
+ EntityProcessErrors,
+ hasErrors,
isOrphan,
} from '@backstage/plugin-catalog';
import {
@@ -223,6 +225,13 @@ const overviewContent = (
+
+
+
+
+
+
+
diff --git a/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.test.tsx b/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.test.tsx
new file mode 100644
index 0000000000..28f4f92a27
--- /dev/null
+++ b/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.test.tsx
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { EntityProvider } from '@backstage/plugin-catalog-react';
+
+import { renderInTestApp } from '@backstage/test-utils';
+import React from 'react';
+import { EntityProcessErrors } from './EntityProcessErrors';
+import { Entity } from '@backstage/catalog-model';
+import { waitFor } from '@testing-library/react';
+
+describe('', () => {
+ it('renders EntityProcessErrors if the entity has errors', async () => {
+ const entity: Entity = {
+ apiVersion: 'v1',
+ kind: 'Component',
+ metadata: {
+ name: 'software',
+ description: 'This is the description',
+ },
+
+ spec: {
+ owner: 'guest',
+ type: 'service',
+ lifecycle: 'production',
+ },
+ status: {
+ items: [
+ {
+ type: 'backstage.io/catalog-processing',
+ level: 'error',
+ message:
+ 'InputError: Policy check failed; caused by Error: Malformed envelope, /metadata/labels should be object',
+ error: {
+ name: 'InputError',
+ message:
+ 'Policy check failed; caused by Error: Malformed envelope, /metadata/labels should be object',
+ cause: {
+ name: 'Error',
+ message:
+ 'Malformed envelope, /metadata/labels should be object',
+ },
+ },
+ },
+ {
+ type: 'backstage.io/catalog-processing',
+ level: 'error',
+ message: 'InputError: Foo',
+ error: {
+ name: 'InputError',
+ message: 'Foo',
+ cause: {
+ name: 'Error',
+ message:
+ 'Malformed envelope, /metadata/labels should be object',
+ },
+ },
+ },
+ ],
+ },
+ };
+
+ const { getByText } = await renderInTestApp(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(
+ getByText(
+ 'Error: Policy check failed; caused by Error: Malformed envelope, /metadata/labels should be object',
+ ),
+ ).toBeInTheDocument();
+ expect(getByText('Error: Foo')).toBeInTheDocument();
+ });
+ });
+});
diff --git a/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.tsx b/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.tsx
new file mode 100644
index 0000000000..3d1210290a
--- /dev/null
+++ b/plugins/catalog/src/components/EntityProcessErrors/EntityProcessErrors.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Entity } from '@backstage/catalog-model';
+import { useEntity } from '@backstage/plugin-catalog-react';
+import { Box } from '@material-ui/core';
+import React from 'react';
+import { ResponseErrorPanel } from '@backstage/core-components';
+
+export const hasErrors = (entity: Entity) => entity?.status?.items?.length! > 0;
+
+/**
+ * Displays a list of errors if the entity is invalid.
+ */
+export const EntityProcessErrors = () => {
+ const { entity } = useEntity();
+
+ return (
+ <>
+ {entity?.status?.items?.map(
+ ({ error }, index) =>
+ error && (
+
+
+
+ ),
+ )}
+ >
+ );
+};
diff --git a/plugins/catalog/src/components/EntityProcessErrors/index.ts b/plugins/catalog/src/components/EntityProcessErrors/index.ts
new file mode 100644
index 0000000000..10d6d04ed2
--- /dev/null
+++ b/plugins/catalog/src/components/EntityProcessErrors/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { EntityProcessErrors, hasErrors } from './EntityProcessErrors';
diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts
index 4bef0950a2..d3f5d8e36b 100644
--- a/plugins/catalog/src/index.ts
+++ b/plugins/catalog/src/index.ts
@@ -23,6 +23,7 @@ export type { EntityRow as CatalogTableRow } from './components/CatalogTable';
export { CreateComponentButton } from './components/CreateComponentButton';
export { EntityLayout } from './components/EntityLayout';
export * from './components/EntityOrphanWarning';
+export * from './components/EntityProcessErrors';
export { EntityPageLayout } from './components/EntityPageLayout';
export * from './components/EntitySwitch';
export { Router } from './components/Router';