Skip to content

[ISSUE] cannot reset reader of type io.nopCloserWriterTo when retrying OIDC authentication #1398

@orf

Description

@orf

Description
If the Databricks OIDC endpoint returns a retriable error, token authentication fails with cannot reset reader of type io.nopCloserWriterTo from here:

func (r RequestBody) Reset() error {
if r.Reader == nil {
return nil
}
if v, ok := r.Reader.(io.Seeker); ok {
_, err := v.Seek(0, io.SeekStart)
return err
} else {
return fmt.Errorf("cannot reset reader of type %T", r.Reader)
}

This is because the google OIDC library creates a request here https://github.com/golang/oauth2/blob/acc38155b7f6f36aefcb58faff6f36d314dd915c/internal/token.go#L225 which wraps the body in a io.ReadCloser here https://github.com/golang/go/blob/b28808d838682b2911698fcb934813b02f39fa69/src/net/http/request.go#L908

Reproduction

package main

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"os"
	"path/filepath"

	"github.com/databricks/databricks-sdk-go"
)

type hc func(r *http.Request) (*http.Response, error)

func (cb hc) RoundTrip(r *http.Request) (*http.Response, error) {
	return cb(r)
}

func main() {
	fsDir, err := os.MkdirTemp("", "tree_*")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(fsDir)
	filePath := filepath.Join(fsDir, "token")
	err = os.WriteFile(filePath, []byte("test-token"), os.ModePerm)
	if err != nil {
		panic(err)
	}

	cfg := &databricks.Config{
		AuthType: "file-oidc",
		OIDCTokenFilepath: filePath,
		Host: "https://accounts.cloud.databricks.com/",
		AccountID: "test-account",
		HTTPTransport: hc(func(r *http.Request) (*http.Response, error) {
			bodyBytes, err := json.Marshal(map[string]string{
				"error": "too many requests",
			})
			if err != nil {
				panic(err)
			}

			return &http.Response{
				StatusCode:    http.StatusTooManyRequests,
				Body:          io.NopCloser(bytes.NewReader(bodyBytes)),
				ContentLength: int64(len(bodyBytes)),
				Header: map[string][]string{
					"Content-Type": {"application/json"},
				},
				Request: r,
			}, nil
		}),
	}
	c, err := databricks.NewAccountClient(cfg)
	if err != nil{
		panic(err)
	}
	_, err = c.Config.GetTokenSource().Token(context.TODO())
	if err != nil {
		panic(err)
	}
}

Expected behavior
The request should be retried

Is it a regression?
No

Debug Logs

2025/12/31 14:13:45 [TRACE] Loading config via environment
2025/12/31 14:13:45 [TRACE] Loading config via config-file
2025/12/31 14:13:45 [TRACE] Attempting to configure auth: "file-oidc"
2025/12/31 14:13:45 [DEBUG] No ClientID provided, authenticating with Account-wide token federation
2025/12/31 14:13:45 [DEBUG] POST /oidc/accounts/test-account/v1/token
> <http.RoundTripper>
<  
< {
<   "error": "too many requests"
< }
2025/12/31 14:13:45 [DEBUG] Attempting retry because of "too many requests"
2025/12/31 14:13:45 [DEBUG] non-retriable error: cannot reset reader of type io.nopCloserWriterTo
panic: file-oidc auth: Post "https://accounts.cloud.databricks.com/oidc/accounts/test-account/v1/token": cannot reset reader of type io.nopCloserWriterTo. Config: host=https://accounts.cloud.databricks.com, account_id=test-account, databricks_id_token_filepath=/var/folders/r1/myg4s_g127d6pjrb1rbry1_80000gn/T/tree_908089712/token

Other Information

  • OS: [e.g. macOS]: MacOS
  • Version: [e.g. 0.1.0]: Latest

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThe issue is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions