PuerkitoBio/goquery · error

Response.Request is nil

Error message

Response.Request is nil

What it means

NewDocumentFromResponse requires res.Request (the request that generated the response) to be non-nil, because it uses res.Request.URL to resolve relative links when building the Document. If the response was constructed manually (e.g. httptest.ResponseRecorder or &http.Response{} literal) without setting Request, this error is returned.

Source

Thrown at type.go:70

	root, e := html.Parse(r)
	if e != nil {
		return nil, e
	}
	return newDocument(root, nil), nil
}

// NewDocumentFromResponse is another Document constructor that takes an http response as argument.
// It loads the specified response's document, parses it, and stores the root Document
// node, ready to be manipulated. The response's body is closed on return.
//
// Deprecated: Use goquery.NewDocumentFromReader with the response's body.
func NewDocumentFromResponse(res *http.Response) (*Document, error) {
	if res == nil {
		return nil, errors.New("Response is nil")
	}
	defer res.Body.Close()
	if res.Request == nil {
		return nil, errors.New("Response.Request is nil")
	}

	// Parse the HTML into nodes
	root, e := html.Parse(res.Body)
	if e != nil {
		return nil, e
	}

	// Create and fill the document
	return newDocument(root, res.Request.URL), nil
}

// CloneDocument creates a deep-clone of a document.
func CloneDocument(doc *Document) *Document {
	return newDocument(cloneNode(doc.rootNode), doc.Url)
}

// Private constructor, make sure all fields are correctly filled.

View on GitHub (pinned to 738783cbc3)

Solutions

  1. Assign a request to the response before parsing: res.Request = &http.Request{Method: "GET", URL: parsedURL}.
  2. In tests, set httptest.NewRequest(...) and recorder.Result().Request = req, or use http.Client against httptest.Server so Request is populated.
  3. Use goquery.NewDocumentFromReader(res.Body) if you do not need URL-based relative-link resolution.

Example fix

// before
rec := httptest.NewRecorder()
rec.WriteString("<html></html>")
doc, err := goquery.NewDocumentFromResponse(rec.Result()) // Request is nil

// after
req := httptest.NewRequest("GET", "http://example.com/", nil)
rec := httptest.NewRecorder()
rec.WriteString("<html></html>")
res := rec.Result()
res.Request = req
doc, err := goquery.NewDocumentFromResponse(res)
Defensive patterns

Strategy: validation

Validate before calling

if res == nil || res.Request == nil || res.Request.URL == nil {
	return errors.New("response lacks Request/URL context")
}
doc, err := goquery.NewDocumentFromResponse(res)

Type guard

func hasRequestContext(res *http.Response) bool {
	return res != nil && res.Request != nil && res.Request.URL != nil
}

Prevention

When it happens

Trigger: Passing an *http.Response that was hand-constructed or produced by httptest.NewRecorder().Result() without assigning res.Request; responses from clients that do not populate Request.

Common situations: Unit tests building fake responses with httptest where only Body/StatusCode were set; deserialized responses from caches or mocks; constructing a response from a saved payload and forgetting Request.URL.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of PuerkitoBio/goquery@738783cbc3 (2026-09-06). Data as JSON: /api/errors/8a4ffcdf7995db89. Report an issue: GitHub.