{"record":{"id":"39355a16957c24c2","repo":"gofiber/fiber","slug":"client-cannot-be-nil","errorCode":null,"errorMessage":"client cannot be nil","messagePattern":"client cannot be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/request.go","lineNumber":42,"sourceCode":"\tAdd(name, obj string)\n\tDel(name string)\n}\n\n// bodyType defines the type of request body.\ntype bodyType int\n\n// Enumeration of request body types.\nconst (\n\tnoBody bodyType = iota\n\tjsonBody\n\txmlBody\n\tformBody\n\tfilesBody\n\trawBody\n\tcborBody\n)\n\nvar ErrClientNil = errors.New(\"client cannot be nil\")\n\n// Request contains all data related to an HTTP request.\ntype Request struct {\n\tctx context.Context //nolint:containedctx // Context is needed to be stored in the request.\n\n\tbody    any\n\theader  Header\n\tparams  QueryParam\n\tcookies Cookie\n\tpath    PathParam\n\n\tclient *Client\n\n\tformData FormData\n\n\tRawRequest *fasthttp.Request\n\turl        string\n\tmethod     string","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/request.go#L24-L60","documentation":"Has two failure modes. (1) PANIC: Request.SetClient(nil) panics with ErrClientNil (client/request.go:105) because a request without a client cannot execute. (2) RETURNED error: Response.JSON/CBOR/XML return ErrClientNil (client/response.go:158,167,176) when r.client == nil, because the (de)serialization function lives on the client and is unreachable.","triggerScenarios":"Calling req.SetClient(nil); using a Response whose client was cleared (e.g. after Reset() or a pooled response reused without setClient); calling resp.JSON() on a Response acquired from a non-client source; unit tests that build a Response manually.","commonSituations":"Reusing a pooled Response after Reset() zeroed r.client; returning a Response from a goroutine that lost its client reference; test helpers that construct fiber.Response{} directly; refactoring that drops the SetClient call.","solutions":["Always pair Request with a non-nil Client: req := client.Get(); do not call req.SetClient(nil).","After acquiring a Response from the pool, ensure setClient was called (the normal Do path does this in core.go:109).","In tests, construct responses through the client or call the package-level acquire helper that sets the client.","For Response.JSON/CBOR/XML, if you only have the body bytes, unmarshal them directly with the codec instead of going through resp.JSON()."],"exampleFix":"// before (panic)\nreq.SetClient(nil) // panic: ErrClientNil\n\n// before (returned)\nresp := acquireOrphanResponse()\nerr := resp.JSON(&v) // ErrClientNil\n\n// after\nreq := client.Get().SetURL(u) // request keeps its client\nresp, err := req.Send()\nerr = resp.JSON(&v) // client present","handlingStrategy":"validation","validationCode":"func ensureClient(req *fiber.Request, c *fiber.Client) error {\n    if c == nil { return fiber.ErrClientNil }\n    req.SetClient(c)\n    return nil\n}","typeGuard":"func hasClient(r *fiber.Response) bool { return r != nil && r.Client() != nil }","tryCatchPattern":"if err := resp.JSON(&v); err != nil {\n    if errors.Is(err, fiber.ErrClientNil) {\n        // unmarshal the body directly with the codec instead\n        err = json.Unmarshal(resp.Body(), &v)\n    }\n}","preventionTips":["Always create requests via client.Get/Post/... so the client is set.","Do not call req.SetClient(nil).","Do not reuse a Response after Reset() zeroed its client — reacquire from a client call."],"tags":["client","request","response","panic","configuration"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}