You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
waitForIpniProviderResults returns Promise<boolean> and on failure throws a single Error whose message references one CID (the last one checked). Consumers cannot tell, after the fact, which CIDs in [rootCid, ...childBlocks] were verified vs. timed out vs. missing-expected-provider vs. fetch-errored.
This matters most on the abort/timeout path: when an outer AbortSignal.timeout(...) fires mid-walk, the in-flight fetch throws AbortError and we lose which CID was current and which CIDs had already been verified successfully.
Concrete example from the dealbot consumer (FilOzone/dealbot):
Deals are uploaded with rootCID + ~12 childBlocks. Outer timeout 60s, delayMs 2500ms, so each CID gets ~25 attempts.
7 of 8 SPs verify cleanly at p50 ~2.4s. SP6 (Hangzhou CN) verifies at p50 ~31s with 39% slow_verification rate; ~22 deals/24h time out at the 60s budget.
All timeouts surface as a single generic message. We currently cannot distinguish "rootCID never indexed" from "rootCID indexed but childBlock N never indexed."
In observed dealbot data, all timeouts are wall-clock SLO breaches, not selective "missing expected provider" failures. Per-CID granularity would not have shifted root-cause attribution (path quality between filecoinpin.contact / Reston VA and SP6 / Hangzhou CN, AS4134 ChinaNet, ICMP packet loss 24% from a peer test vantage).
At dealbot's current SLO budget (60s with 2.5s polls and 12 CIDs), only the first 4-5 CIDs get any attempts before the outer abort fires anyway — so child-CID granularity is not measurable end-to-end without also rebudgeting.
Existing single-error throw can be preserved as a thin wrapper for callers that prefer the boolean shape, or replaced with always returning the outcome and letting callers decide whether to throw.
Acceptance criteria
waitForIpniProviderResults returns or exposes per-CID verified/failed lists.
Problem
waitForIpniProviderResultsreturnsPromise<boolean>and on failure throws a singleErrorwhose message references one CID (the last one checked). Consumers cannot tell, after the fact, which CIDs in[rootCid, ...childBlocks]were verified vs. timed out vs. missing-expected-provider vs. fetch-errored.This matters most on the abort/timeout path: when an outer
AbortSignal.timeout(...)fires mid-walk, the in-flightfetchthrowsAbortErrorand we lose which CID was current and which CIDs had already been verified successfully.Concrete example from the dealbot consumer (FilOzone/dealbot):
Why this is currently low priority
Error.cause.Proposal (when prioritized)
Change return type from
Promise<boolean>to something like:```ts
type IpniValidationOutcome = {
verified: Array<{ cid: CID; matchedAt: number; attempts: number }>;
failed: Array<{
cid: CID;
reason:
| { type: 'timeout'; attempts: number }
| { type: 'missingProviders'; missingServiceUrls: string[]; actualMultiaddrs: string[] }
| { type: 'fetch'; message: string }
| { type: 'parse'; message: string }
| { type: 'http'; status: number; statusText?: string };
}>;
ipniIndexerUrl: string;
};
```
Existing single-error throw can be preserved as a thin wrapper for callers that prefer the boolean shape, or replaced with always returning the outcome and letting callers decide whether to throw.
Acceptance criteria
waitForIpniProviderResultsreturns or exposes per-CID verified/failed lists.setTimeout(delayMs)(currently signal-unaware at https://github.com/filecoin-project/filecoin-pin/blob/main/src/core/utils/validate-ipni-advertisement.ts#L387) is preserved or fixed in the same change. Optional related fix: make the inter-attempt sleep signal-aware so abort overshoot is bounded by the in-flight fetch rather than bydelayMs.Consumer signal
Open this when: