diff --git a/frontend/src/features/flows/files/flow-files-pull-dialog.tsx b/frontend/src/features/flows/files/flow-files-pull-dialog.tsx
index 5e38fe7a..4332a6bc 100644
--- a/frontend/src/features/flows/files/flow-files-pull-dialog.tsx
+++ b/frontend/src/features/flows/files/flow-files-pull-dialog.tsx
@@ -1,4 +1,4 @@
-import { ArrowDownToLine, ArrowUp, FolderOpen, Loader2, RefreshCw } from 'lucide-react';
+import { ArrowDownToLine, ArrowUp, FolderOpen, Loader2, RefreshCw, TriangleAlert } from 'lucide-react';
import { useCallback, useMemo, useState } from 'react';
import {
@@ -8,6 +8,7 @@ import {
type FileNode,
} from '@/components/shared/file-manager';
import { OverwriteButtons, OverwriteDialog, useOverwrite } from '@/components/shared/overwrite';
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import {
Autocomplete,
AutocompleteContent,
@@ -133,6 +134,7 @@ function FlowFilesPullDialogForm({ cachedFiles, flowId, onClose, onSuccess }: Fl
const {
error: listingError,
+ failures: listingFailures,
files,
isLoading: isListingLoading,
refetch: refetchListing,
@@ -331,6 +333,18 @@ function FlowFilesPullDialogForm({ cachedFiles, flowId, onClose, onSuccess }: Fl
{listingError.message}
+ ) : listingFailures.length > 0 ? (
+
+
+
+
+
+ Nothing readable here
+
+ None of the entries in {currentPath} could be read.
+
+
+
) : (
@@ -424,6 +438,24 @@ function FlowFilesPullDialogForm({ cachedFiles, flowId, onClose, onSuccess }: Fl
+ {listingFailures.length > 0 && flatFiles.length > 0 && (
+
+
+
+ {listingFailures.length} {listingFailures.length === 1 ? 'entry' : 'entries'} could not
+ be read
+
+
+ The readable entries are shown below. Skipped:{' '}
+ {listingFailures
+ .slice(0, 5)
+ .map((failure) => failure.name)
+ .join(', ')}
+ {listingFailures.length > 5 ? `, and ${listingFailures.length - 5} more` : ''}.
+
+
+ )}
+
([]);
+ const [failures, setFailures] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
@@ -65,6 +73,7 @@ export function useFlowContainerFiles({ flowId, paths }: UseFlowContainerFilesPa
if (!flowId || paths.length === 0) {
currentTokenRef.current += 1;
setFiles([]);
+ setFailures([]);
setIsLoading(false);
setError(null);
@@ -89,6 +98,7 @@ export function useFlowContainerFiles({ flowId, paths }: UseFlowContainerFilesPa
}
setFiles(data.files.map(containerFileToFileNode));
+ setFailures(data.failures ?? []);
} catch (caught) {
if (token !== currentTokenRef.current) {
return;
@@ -96,6 +106,7 @@ export function useFlowContainerFiles({ flowId, paths }: UseFlowContainerFilesPa
setError(new Error(getApiErrorMessage(caught, 'Failed to load container files')));
setFiles([]);
+ setFailures([]);
} finally {
if (token === currentTokenRef.current) {
setIsLoading(false);
@@ -116,6 +127,7 @@ export function useFlowContainerFiles({ flowId, paths }: UseFlowContainerFilesPa
return {
error,
+ failures,
files,
isLoading,
refetch: fetchListing,