{"record":{"id":"898f18f1b396b466","repo":"ipfs/kubo","slug":"s-w-898f18","errorCode":null,"errorMessage":"%s : %w","messagePattern":"%s : %w","errorType":"exception","errorClass":null,"httpStatus":503,"severity":"warning","filePath":"core/corehttp/gateway.go","lineNumber":206,"sourceCode":"\n\tbackend, err := gateway.NewBlocksBackend(bserv,\n\t\tgateway.WithValueStore(vsRouting),\n\t\tgateway.WithNameSystem(nsys),\n\t\tgateway.WithResolver(pathResolver),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &offlineGatewayErrWrapper{gwimpl: backend}, nil\n}\n\ntype offlineGatewayErrWrapper struct {\n\tgwimpl gateway.IPFSBackend\n}\n\nfunc offlineErrWrap(err error) error {\n\tif errors.Is(err, iface.ErrOffline) {\n\t\treturn fmt.Errorf(\"%s : %w\", err.Error(), gateway.ErrServiceUnavailable)\n\t}\n\treturn err\n}\n\nfunc (o *offlineGatewayErrWrapper) Get(ctx context.Context, path path.ImmutablePath, ranges ...gateway.ByteRange) (gateway.ContentPathMetadata, *gateway.GetResponse, error) {\n\tmd, n, err := o.gwimpl.Get(ctx, path, ranges...)\n\terr = offlineErrWrap(err)\n\treturn md, n, err\n}\n\nfunc (o *offlineGatewayErrWrapper) GetAll(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, files.Node, error) {\n\tmd, n, err := o.gwimpl.GetAll(ctx, path)\n\terr = offlineErrWrap(err)\n\treturn md, n, err\n}\n\nfunc (o *offlineGatewayErrWrapper) GetBlock(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, files.File, error) {\n\tmd, n, err := o.gwimpl.GetBlock(ctx, path)","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/corehttp/gateway.go#L188-L224","documentation":"offlineErrWrap decorates errors from the gateway backend when the gateway runs in offline mode. If the underlying backend returns iface.ErrOffline (a required piece of content or IPNS record is not available locally and fetching is disabled), it rewrites the error as '<original message> : service unavailable' so the gateway can map it to an HTTP 503 for the client.","triggerScenarios":"Requesting a path through an HTTP gateway (Get, Head, GetCAR, ResolvePath, GetAll, GetBlock) when `Gateway.NoFetch` is true (offline gateway) and the blocks or IPNS record needed to serve the path are not present in the local datastore.","commonSituations":"Operating a public gateway with NoFetch=true and clients requesting content that was never added or pinned locally; IPNS name resolution on an offline gateway with no cached record; trustless/CAR requests for blocks absent from the store; misconfigured gateways where operators expect fetch-on-demand but NoFetch is enabled.","solutions":["Preload the requested content locally: `ipfs get <cid>` or pin it (`ipfs pin add <cid>`) on the gateway node before serving.","If the gateway should fetch on demand, disable offline mode: `ipfs config --json Gateway.NoFetch false` and restart the daemon.","For IPNS names, publish/resolve while online once so the record is cached, or serve only DNSLink/record-backed names with records present.","Treat the HTTP 503 on the client side as 'content not locally available' and retry after the gateway operator preloads it."],"exampleFix":"// before: offline gateway, content missing -> 503\n// Gateway.NoFetch = true; request /ipfs/<unpinned-cid>\n\n// after: preload then serve\nipfs config --json Gateway.NoFetch false  # or:\nipfs pin add <cid>                        # ensure local availability","handlingStrategy":"fallback","validationCode":"// client-side preflight for an offline gateway\nhasLocal, err := hasLocally(api, cid) // e.g. `ipfs dag stat --local` or blockstore check\nif err != nil { return err }\nif !hasLocal {\n    return fmt.Errorf(\"gateway is offline (NoFetch=true); content %s must be pinned locally first\", cid)\n}","typeGuard":"func isOfflineUnavailable(err error) bool {\n    // surfaced as HTTP 503 with the original message + 'service unavailable'\n    return errors.Is(err, gateway.ErrServiceUnavailable) ||\n        errors.Is(err, iface.ErrOffline)\n}","tryCatchPattern":"md, resp, err := backend.Get(ctx, p)\nif err != nil {\n    if errors.Is(err, gateway.ErrServiceUnavailable) || errors.Is(err, iface.ErrOffline) {\n        return nil, fmt.Errorf(\"content unavailable offline: %w\", err) // map to 503 / trigger pinning\n    }\n    return err\n}","preventionTips":["Pin or pre-warm all content an offline gateway is expected to serve.","Set Gateway.NoFetch=false unless you deliberately run a cache-only gateway.","Monitor 503 rates on offline gateways as a signal of missing local content.","For IPNS names, resolve and cache records while the node is online."],"tags":["gateway","offline","ipns","http-503"],"backgroundTag":"gateway-offline-unavailable","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}