From d3edd75e822df16391e21f9cd2649f10a468a2a0 Mon Sep 17 00:00:00 2001 From: Chris Burr Date: Thu, 29 Jan 2026 06:18:11 +0100 Subject: [PATCH] fix: Return structured errors from GFAL2 storage operations Return error dictionaries with errno codes from exists() and getFileMetadata() to allow consumers to distinguish between different error types (e.g., ENOENT vs EACCES). This enables downstream code to properly handle permission denied errors separately from file-not-found errors, avoiding false positives when checking file existence at storage elements. --- src/DIRAC/Resources/Storage/GFAL2_StorageBase.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/DIRAC/Resources/Storage/GFAL2_StorageBase.py b/src/DIRAC/Resources/Storage/GFAL2_StorageBase.py index f1137048330..4905e5e17e9 100644 --- a/src/DIRAC/Resources/Storage/GFAL2_StorageBase.py +++ b/src/DIRAC/Resources/Storage/GFAL2_StorageBase.py @@ -230,8 +230,10 @@ def exists(self, path): for url in urls: try: successful[url] = self.__singleExists(url) + except gfal2.GError as e: + failed[url] = {"error": repr(e), "errno": e.code} except Exception as e: - failed[url] = repr(e) + failed[url] = {"error": repr(e), "errno": None} resDict = {"Failed": failed, "Successful": successful} return resDict @@ -636,9 +638,10 @@ def getFileMetadata(self, path): for url in urls: try: successful[url] = self._getSingleFileMetadata(url) - + except gfal2.GError as e: + failed[url] = {"error": repr(e), "errno": e.code} except Exception as e: - failed[url] = repr(e) + failed[url] = {"error": repr(e), "errno": None} return {"Failed": failed, "Successful": successful}