ipfs/kubo · error

unexpected redirect

Error message

unexpected redirect

What it means

The RPC HTTP client explicitly disables HTTP redirects in NewApi by setting httpcli.CheckRedirect to always return 'unexpected redirect'. The kubo RPC is a single flat /api/v0/ surface and redirects usually indicate a misconfigured endpoint (e.g. a gateway URL, a proxy login page, or trailing-slash rewrite), so the client fails fast instead of silently following to a different service.

Source

Thrown at client/rpc/api.go:179

func NewURLApiWithClient(url string, c *http.Client) (*HttpApi, error) {
	decoder := legacy.NewDecoder()
	// Add support for these codecs to match what is done in the merkledag library
	// Note: to match prior behavior the go-ipld-prime CBOR decoder is manually included
	// TODO: allow the codec registry used to be configured by the caller not through a global variable
	decoder.RegisterCodec(cid.DagProtobuf, dagpb.Type.PBNode, merkledag.ProtoNodeConverter)
	decoder.RegisterCodec(cid.Raw, basicnode.Prototype.Bytes, merkledag.RawNodeConverter)

	api := &HttpApi{
		url:         url,
		httpcli:     *c,
		Headers:     make(map[string][]string),
		applyGlobal: func(*requestBuilder) {},
		ipldDecoder: decoder,
	}

	// We don't support redirects.
	api.httpcli.CheckRedirect = func(_ *http.Request, _ []*http.Request) error {
		return fmt.Errorf("unexpected redirect")
	}

	return api, nil
}

func (api *HttpApi) WithOptions(opts ...caopts.ApiOption) (iface.CoreAPI, error) {
	options, err := caopts.ApiOptions(opts...)
	if err != nil {
		return nil, err
	}

	subApi := &HttpApi{
		url:     api.url,
		httpcli: api.httpcli,
		Headers: api.Headers,
		applyGlobal: func(req *requestBuilder) {
			if options.Offline {
				req.Option("offline", options.Offline)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Use the direct, non-redirecting API address (e.g. http://127.0.0.1:5001) with no trailing redirects
  2. Test the URL with `curl -i <url>/api/v0/id` and remove whatever causes the 3xx
  3. Reconfigure proxy/ingress to pass requests through without rewriting (disable http->https or slash redirects for /api/v0)
  4. If a redirect is genuinely required, supply your own http.Client by constructing HttpApi with a custom option rather than relying on the default client

Example fix

// before
api, err := rpc.NewApi("http://127.0.0.1:8080") // gateway, gets redirected
// after
api, err := rpc.NewApi("http://127.0.0.1:5001") // actual RPC API port
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(apiURL)
if err != nil { return err }
if u.Port() != "5001" && !strings.Contains(u.Path, "/api/v0") {
    return fmt.Errorf("%s does not look like a kubo RPC API endpoint", apiURL)
}

Try / catch

api, err := rpc.NewApi(apiURL)
if err != nil && strings.Contains(err.Error(), "unexpected redirect") {
    return fmt.Errorf("endpoint %s redirects; use the direct RPC address (port 5001), not a gateway or proxy: %w", apiURL, err)
}

Prevention

When it happens

Trigger: Pointing the RPC client at a URL that 3xx-redirects: a gateway address instead of the API port, an HTTPS/HTTP mismatch behind a proxy, a load balancer sending 301/302, or a base URL missing/extra path segments causing server-side rewrites.

Common situations: Users configuring http://127.0.0.1:8080 (gateway) instead of :5001 (API); reverse proxies with auto-redirect rules (http->https, /api/v0 -> /api/v0/); IPFS Desktop or cluster setups pointing at proxied endpoints; cloud deployments fronting the daemon with an ingress that redirects.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/9ae578fe06c9b74c. Report an issue: GitHub.