Skip to content

fix: WithHTTPClient(nil) panics with a nil pointer dereference on the first request - #45

Merged
karlwaldman merged 1 commit into
mainfrom
fix/nil-http-client
Sep 13, 2026
Merged

karlwaldman merged 1 commit into
mainfrom
fix/nil-http-client

Conversation

@karlwaldman

Copy link
Copy Markdown
Member

Closes #41

The defect

WithHTTPClient stored its argument verbatim. WithHTTPClient(nil) therefore left Client.httpClient nil and httpClient.Do(req) dereferenced it on the first request.

A nil arrives from ordinary code: a client read out of a config struct, or returned alongside an error by a helper whose error the caller did not check. The SDK already returns a typed *ConfigurationError rather than panicking for the equivalent bad input (a negative WithRetries), so panicking here was inconsistent as well as hostile.

Verified still reproducing on main (cd51e3a) before any change was written.

The fix

A nil *http.Client is ignored and the SDK keeps its default, exactly as if the option had not been supplied. One guard in WithHTTPClient, plus the doc comment stating the contract.

Explicit configuration is preserved either way round: WithHTTPClient(nil), WithTimeout(7s) and WithTimeout(7s), WithHTTPClient(nil) both leave a 7s timeout; a bare WithHTTPClient(nil) leaves DefaultTimeout.

Red

Tests written first, run against unmodified origin/main client.go (git checkout origin/main -- client.go):

--- FAIL: TestWithHTTPClientNilDoesNotPanic (0.00s)
    nil_http_client_test.go:36: WithHTTPClient(nil) left the client with a nil *http.Client
--- FAIL: TestWithHTTPClientNilKeepsDefaultTimeout (0.00s)
    nil_http_client_test.go:50: WithHTTPClient(nil) left the client with a nil *http.Client
--- FAIL: TestWithHTTPClientNilPreservesExplicitTimeout (0.00s)
    --- FAIL: TestWithHTTPClientNilPreservesExplicitTimeout/nil_then_timeout (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x2 addr=0x28 pc=0x104797c18]
...
github.com/OilpriceAPI/oilpriceapi-go.TestWithHTTPClientNilPreservesExplicitTimeout.WithTimeout.func3(...)
	client.go:118

Green

=== RUN   TestWithHTTPClientNilDoesNotPanic
--- PASS: TestWithHTTPClientNilDoesNotPanic (0.01s)
=== RUN   TestWithHTTPClientNilKeepsDefaultTimeout
--- PASS: TestWithHTTPClientNilKeepsDefaultTimeout (0.00s)
=== RUN   TestWithHTTPClientNilPreservesExplicitTimeout
--- PASS: TestWithHTTPClientNilPreservesExplicitTimeout (0.00s)
    --- PASS: TestWithHTTPClientNilPreservesExplicitTimeout/nil_then_timeout (0.00s)
    --- PASS: TestWithHTTPClientNilPreservesExplicitTimeout/timeout_then_nil (0.00s)
PASS
ok  	github.com/OilpriceAPI/oilpriceapi-go	0.022s

Full suite

Check Result
go test ./... ok github.com/OilpriceAPI/oilpriceapi-go 16.490s — 290 pass / 0 fail (285 baseline + 5 new)
go test -race ./... ok github.com/OilpriceAPI/oilpriceapi-go 18.355s
go vet ./... clean
gofmt -l . clean

Interaction with #38

The #38 PR (fix/timeout-clone) also stops Client.httpClient from ever being the caller's own pointer. The two branches touch different functions and do not conflict in either merge order; this guard remains the explicit statement of the nil contract regardless of which lands first.

Scope

No version bump, no tag, no release. Public API unchanged — this only removes a panic.

🤖 Generated with Claude Code

https://claude.ai/code/session_015ao5paex73xXvuM424Libo

WithHTTPClient stored its argument verbatim, so WithHTTPClient(nil) left
Client.httpClient nil and the first request dereferenced it:

    panic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x2 addr=0x28]

A nil arrives from ordinary code — a client read out of a config struct, or
returned alongside an error by a helper the caller did not check. That is a
misconfiguration, not a reason to take the process down, and the SDK already
returns *ConfigurationError rather than panicking for the equivalent bad
retry count.

A nil client is now ignored and the SDK keeps its default, exactly as if the
option had not been supplied. The default request timeout survives, and an
explicitly configured WithTimeout survives in either option order.

Closes #41

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ao5paex73xXvuM424Libo
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 5d12bf9b-43f5-4220-b527-a4e8694b7848


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@karlwaldman
karlwaldman merged commit 6552557 into main Sep 13, 2026
9 checks passed
@karlwaldman
karlwaldman deleted the fix/nil-http-client branch September 13, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P3] WithHTTPClient(nil) panics with a nil pointer dereference on the first request

1 participant