Skip to content

Commit 906ce80

Browse files
authored
feat(gateway): improved error page with retrieval state details (#10950)
* feat(gateway): add DiagnosticServiceURL config - add Gateway.DiagnosticServiceURL to kubo config - pass diagnostic service URL to boxo gateway - document new config option in docs/config.md - default to https://check.ipfs.network * docs(changelog): add gateway error UX improvements to v0.38 - document improved 504 error pages with retrieval diagnostics - highlight new Gateway.DiagnosticServiceURL config option - include screenshot showing enhanced error page UX
1 parent 6faa9d8 commit 906ce80

File tree

10 files changed

+41
-12
lines changed

10 files changed

+41
-12
lines changed

config/gateway.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const (
99
DefaultDeserializedResponses = true
1010
DefaultDisableHTMLErrors = false
1111
DefaultExposeRoutingAPI = false
12+
DefaultDiagnosticServiceURL = "https://check.ipfs.network"
1213

1314
// Gateway limit defaults from boxo
1415
DefaultRetrievalTimeout = gateway.DefaultRetrievalTimeout
@@ -98,4 +99,10 @@ type Gateway struct {
9899
// Requests beyond this limit receive 429 Too Many Requests with Retry-After header.
99100
// A value of 0 disables the limit.
100101
MaxConcurrentRequests *OptionalInteger `json:",omitempty"`
102+
103+
// DiagnosticServiceURL is the URL for a service to diagnose CID retrievability issues.
104+
// When the gateway returns a 504 Gateway Timeout error, an "Inspect retrievability of CID"
105+
// button will be shown that links to this service with the CID appended as ?cid=<CID-to-diagnose>.
106+
// Set to empty string to disable the button.
107+
DiagnosticServiceURL *OptionalString `json:",omitempty"`
101108
}

core/corehttp/gateway.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,13 @@ func Libp2pGatewayOption() ServeOption {
107107
// Keep these constraints for security
108108
DeserializedResponses: false, // Trustless-only
109109
NoDNSLink: true, // No DNS resolution
110+
DisableHTMLErrors: true, // Plain text errors only
110111
PublicGateways: nil,
111112
Menu: nil,
112113
// Apply timeout and concurrency limits from user config
113114
RetrievalTimeout: cfg.Gateway.RetrievalTimeout.WithDefault(config.DefaultRetrievalTimeout),
114115
MaxConcurrentRequests: int(cfg.Gateway.MaxConcurrentRequests.WithDefault(int64(config.DefaultMaxConcurrentRequests))),
116+
DiagnosticServiceURL: "", // Not used since DisableHTMLErrors=true
115117
}
116118

117119
handler := gateway.NewHandler(gwConfig, &offlineGatewayErrWrapper{gwimpl: backend})
@@ -270,6 +272,7 @@ func getGatewayConfig(n *core.IpfsNode) (gateway.Config, map[string][]string, er
270272
PublicGateways: map[string]*gateway.PublicGateway{},
271273
RetrievalTimeout: cfg.Gateway.RetrievalTimeout.WithDefault(config.DefaultRetrievalTimeout),
272274
MaxConcurrentRequests: int(cfg.Gateway.MaxConcurrentRequests.WithDefault(int64(config.DefaultMaxConcurrentRequests))),
275+
DiagnosticServiceURL: cfg.Gateway.DiagnosticServiceURL.WithDefault(config.DefaultDiagnosticServiceURL),
273276
}
274277

275278
// Add default implicit known gateways, such as subdomain gateway on localhost.

docs/changelogs/v0.38.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
1818

1919
### 🔦 Highlights
2020

21+
#### 🚨 Improved gateway error pages with diagnostic tools
22+
23+
Gateway error pages now provide more actionable information during content retrieval failures. When a 504 Gateway Timeout occurs, users see detailed retrieval state information including which phase failed and a sample of providers that were attempted:
24+
25+
> ![Improved gateway error page showing retrieval diagnostics](https://github.com/user-attachments/assets/18432c74-a5e0-4bbf-9815-7c780779dc98)
26+
>
27+
> - **[`Gateway.DiagnosticServiceURL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaydiagnosticserviceurl)** (default: `https://check.ipfs.network`): Configures the diagnostic service URL. When set, 504 errors show a "Check CID retrievability" button that links to this service with `?cid=<failed-cid>` for external diagnostics. Set to empty string to disable.
28+
> - **Enhanced error details**: Timeout errors now display the retrieval phase where failure occurred (e.g., "connecting to providers", "fetching data") and up to 3 peer IDs that were attempted but couldn't deliver the content, making it easier to diagnose network or provider issues.
29+
> - **Retry button on all error pages**: Every gateway error page now includes a retry button for quick page refresh without manual URL re-entry.
30+
2131
### 📦️ Important dependency updates
2232

2333
### 📝 Changelog
@@ -26,4 +36,4 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
2636

2737
</details>
2838

29-
### 👨‍👩‍👧‍👦 Contributors
39+
### 👨‍👩‍👧‍👦 Contributors

docs/config.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ config file at runtime.
6969
- [`Gateway.MaxConcurrentRequests`](#gatewaymaxconcurrentrequests)
7070
- [`Gateway.HTTPHeaders`](#gatewayhttpheaders)
7171
- [`Gateway.RootRedirect`](#gatewayrootredirect)
72+
- [`Gateway.DiagnosticServiceURL`](#gatewaydiagnosticserviceurl)
7273
- [`Gateway.FastDirIndexThreshold`](#gatewayfastdirindexthreshold)
7374
- [`Gateway.Writable`](#gatewaywritable)
7475
- [`Gateway.PathPrefixes`](#gatewaypathprefixes)
@@ -1174,6 +1175,16 @@ Default: `""`
11741175

11751176
Type: `string` (url)
11761177

1178+
### `Gateway.DiagnosticServiceURL`
1179+
1180+
URL for a service to diagnose CID retrievability issues. When the gateway returns a 504 Gateway Timeout error, an "Inspect retrievability of CID" button will be shown that links to this service with the CID appended as `?cid=<CID-to-diagnose>`.
1181+
1182+
Set to empty string to disable the button.
1183+
1184+
Default: `"https://check.ipfs.network"`
1185+
1186+
Type: `optionalstring` (url)
1187+
11771188
### `Gateway.FastDirIndexThreshold`
11781189

11791190
**REMOVED**: this option is [no longer necessary](https://github.com/ipfs/kubo/pull/9481). Ignored since [Kubo 0.18](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.18.md).

docs/examples/kubo-as-a-library/go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ go 1.25
77
replace github.com/ipfs/kubo => ./../../..
88

99
require (
10-
github.com/ipfs/boxo v0.34.0
10+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364
1111
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
1212
github.com/libp2p/go-libp2p v0.43.0
1313
github.com/multiformats/go-multiaddr v0.16.1
@@ -82,7 +82,6 @@ require (
8282
github.com/ipfs/go-ds-measure v0.2.2 // indirect
8383
github.com/ipfs/go-ds-pebble v0.5.1 // indirect
8484
github.com/ipfs/go-fs-lock v0.1.1 // indirect
85-
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
8685
github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
8786
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
8887
github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect

docs/examples/kubo-as-a-library/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
287287
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
288288
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
289289
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
290-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
291-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
290+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364 h1:VdRdPlosNYdlENC0UsCxapHala/Q1Me6yBY5ChKUw7s=
291+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
292292
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
293293
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
294294
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/hashicorp/go-version v1.7.0
2323
github.com/ipfs-shipyard/nopfs v0.0.14
2424
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
25-
github.com/ipfs/boxo v0.34.0
25+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364
2626
github.com/ipfs/go-block-format v0.2.2
2727
github.com/ipfs/go-cid v0.5.0
2828
github.com/ipfs/go-cidutil v0.1.0
@@ -146,7 +146,6 @@ require (
146146
github.com/huin/goupnp v1.3.0 // indirect
147147
github.com/ipfs/bbloom v0.0.4 // indirect
148148
github.com/ipfs/go-bitfield v1.1.0 // indirect
149-
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
150149
github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
151150
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
152151
github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
354354
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
355355
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
356356
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
357-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
358-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
357+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364 h1:VdRdPlosNYdlENC0UsCxapHala/Q1Me6yBY5ChKUw7s=
358+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
359359
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
360360
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
361361
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=

test/dependencies/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ require (
134134
github.com/huin/goupnp v1.3.0 // indirect
135135
github.com/inconshreveable/mousetrap v1.1.0 // indirect
136136
github.com/ipfs/bbloom v0.0.4 // indirect
137-
github.com/ipfs/boxo v0.34.0 // indirect
137+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364 // indirect
138138
github.com/ipfs/go-bitfield v1.1.0 // indirect
139139
github.com/ipfs/go-block-format v0.2.2 // indirect
140140
github.com/ipfs/go-cid v0.5.0 // indirect

test/dependencies/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
332332
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
333333
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
334334
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
335-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
336-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
335+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364 h1:VdRdPlosNYdlENC0UsCxapHala/Q1Me6yBY5ChKUw7s=
336+
github.com/ipfs/boxo v0.34.1-0.20250908170437-7d2493027364/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
337337
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
338338
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
339339
github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=

0 commit comments

Comments
 (0)