From e4c99896424b1c4a35a36bd31cfe260bf72ce7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 Jul 2026 15:22:04 -0300 Subject: [PATCH 1/2] fix: aborting entire reconciliation run on a single 401 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- availability-oracle/src/ipfs.rs | 11 +++++++++++ availability-oracle/src/main.rs | 1 + 2 files changed, 12 insertions(+) diff --git a/availability-oracle/src/ipfs.rs b/availability-oracle/src/ipfs.rs index ee17ec4..a0d2c0c 100644 --- a/availability-oracle/src/ipfs.rs +++ b/availability-oracle/src/ipfs.rs @@ -11,6 +11,7 @@ pub enum IpfsError { GatewayTimeout(Cid, Error), // Gateway/Cloudflare timed-out ClientTimeout(Cid, Error), // Client timed-out when requesting the file NotFound(Cid, Error), // Manifest not found + Denied(Cid, Error), // Gateway refuses to serve this object (auth/denylist/removed) Other(Error), } @@ -66,6 +67,12 @@ impl IpfsImpl { } _ if e.is_timeout() => IpfsError::ClientTimeout(cid, e.into()), Some(NOT_FOUND) => IpfsError::NotFound(cid, e.into()), + // The gateway can refuse to serve a specific object (auth, denylist, or + // legal/removed content). This is object-specific, so treat it like a + // missing file rather than aborting the whole reconciliation. + Some(UNAUTHORIZED) | Some(FORBIDDEN) | Some(GONE) | Some(UNAVAILABLE_LEGAL) => { + IpfsError::Denied(cid, e.into()) + } _ => IpfsError::Other(e.into()), }) } @@ -74,6 +81,10 @@ impl IpfsImpl { const CLOUDFLARE_TIMEOUT: u16 = 524; const GATEWAY_TIMEOUT: u16 = 504; const NOT_FOUND: u16 = 404; +const UNAUTHORIZED: u16 = 401; +const FORBIDDEN: u16 = 403; +const GONE: u16 = 410; +const UNAVAILABLE_LEGAL: u16 = 451; #[async_trait] impl Ipfs for IpfsImpl { diff --git a/availability-oracle/src/main.rs b/availability-oracle/src/main.rs index 6c46e71..e4e6b29 100644 --- a/availability-oracle/src/main.rs +++ b/availability-oracle/src/main.rs @@ -572,6 +572,7 @@ impl From for CheckError { CheckError::Invalid(Invalid::Unavailable(cid, err)) } IpfsError::NotFound(cid, err) => CheckError::Invalid(Invalid::Unavailable(cid, err)), + IpfsError::Denied(cid, err) => CheckError::Invalid(Invalid::Unavailable(cid, err)), IpfsError::Other(e) => CheckError::Other(e), } } From 89053d4da8e04447b63cad287b11e1f50751e671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 Jul 2026 15:25:59 -0300 Subject: [PATCH 2/2] chore: remove comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- availability-oracle/src/ipfs.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/availability-oracle/src/ipfs.rs b/availability-oracle/src/ipfs.rs index a0d2c0c..f62ead2 100644 --- a/availability-oracle/src/ipfs.rs +++ b/availability-oracle/src/ipfs.rs @@ -67,9 +67,6 @@ impl IpfsImpl { } _ if e.is_timeout() => IpfsError::ClientTimeout(cid, e.into()), Some(NOT_FOUND) => IpfsError::NotFound(cid, e.into()), - // The gateway can refuse to serve a specific object (auth, denylist, or - // legal/removed content). This is object-specific, so treat it like a - // missing file rather than aborting the whole reconciliation. Some(UNAUTHORIZED) | Some(FORBIDDEN) | Some(GONE) | Some(UNAVAILABLE_LEGAL) => { IpfsError::Denied(cid, e.into()) }