Skip to content

Refactor to use httputil.ReverseProxy#342

Merged
mostlygeek merged 3 commits intomostlygeek:mainfrom
dwrz:reverse-proxy
Oct 13, 2025
Merged

Refactor to use httputil.ReverseProxy#342
mostlygeek merged 3 commits intomostlygeek:mainfrom
dwrz:reverse-proxy

Conversation

@dwrz
Copy link
Copy Markdown
Contributor

@dwrz dwrz commented Oct 9, 2025

Refactor manual HTTP proxying logic in Process.ProxyRequest to use the standard library's httputil.ReverseProxy.

Summary by CodeRabbit

  • Bug Fixes

    • Prevents buffering of server-sent events to improve real-time streaming behavior.
    • Invalid proxy URLs in configuration are now rejected with clear error messages.
  • Refactor

    • Request forwarding switched to a built-in reverse proxy for more reliable upstream handling.
  • Tests

    • Improved streaming test support and recording utilities to better simulate client disconnects and partial responses.

@dwrz dwrz changed the title Reactor to use httputil.ReverseProxy Refactor to use httputil.ReverseProxy Oct 9, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 9, 2025

Walkthrough

Validate model Proxy URLs during config load; add an httputil.ReverseProxy to Process and delegate ProxyRequest to it with a ModifyResponse hook to disable buffering for SSE; add a test response recorder to support CloseNotify and adjust tests for upstream kill/streaming behavior.

Changes

Cohort / File(s) Summary
Config validation
proxy/config/config.go
Import net/url. Parse each model's Proxy string as a URL; on parse failure return error model <id>: invalid proxy URL: <err>. No exported API changes.
Reverse proxy integration
proxy/process.go
Add reverseProxy *httputil.ReverseProxy to Process, initialize it in NewProcess, replace manual proxying in ProxyRequest with p.reverseProxy.ServeHTTP, and add ModifyResponse to set X-Accel-Buffering: no for Content-Type: text/event-stream. Import net/http/httputil.
Process tests adjusted
proxy/process_test.go
Relax assertion in TestProcess_ForceStopWithKill to allow partial/incomplete responses instead of expecting a specific EOF error; add explanatory comments about upstream kill mid-response.
Test response recorder & replacements
proxy/proxymanager_test.go, tests using httptest.NewRecorder() (many files under proxy/...tests)
Add TestResponseRecorder type wrapping httptest.ResponseRecorder with CloseNotify() and closeClient(); add CreateTestResponseRecorder() constructor. Replace uses of httptest.NewRecorder() with the new recorder in streaming-related tests to support CloseNotify behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant P as Process
  participant RP as ReverseProxy
  participant U as Upstream

  Note over P: Process initialized with ReverseProxy (ModifyResponse hook)
  C->>P: HTTP request for proxied model
  P->>RP: ServeHTTP(w, r)
  RP->>U: Forward request upstream
  U-->>RP: Response (may be streaming SSE)
  alt Content-Type == text/event-stream
    Note over RP: ModifyResponse sets X-Accel-Buffering: no
  end
  RP-->>C: Streamed/regular response proxyed back
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • mostlygeek

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly captures the primary change of replacing manual proxy logic with Go’s httputil.ReverseProxy and aligns with the pull request summary describing the refactor of Process.ProxyRequest.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00b738c and 7f0dc14.

📒 Files selected for processing (3)
  • proxy/config/config.go (2 hunks)
  • proxy/config/model_config.go (2 hunks)
  • proxy/process.go (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Fix all staticcheck-reported issues in Go code

Files:

  • proxy/config/config.go
  • proxy/config/model_config.go
  • proxy/process.go
🧬 Code graph analysis (1)
proxy/process.go (1)
proxy/config/model_config.go (1)
  • ModelConfig (11-40)
🪛 GitHub Actions: Linux CI
proxy/config/config.go

[error] Command 'go test -count=1 ./proxy/...' failed during 'make test-all'.

proxy/config/model_config.go

[error] Command 'go test -count=1 ./proxy/...' failed during 'make test-all'.

proxy/process.go

[error] 447-447: TestProcess_AutomaticallyStartsUpstream failed with panic: runtime error: invalid memory address or nil pointer dereference during ProxyRequest (nil pointer dereference in reverse proxy).


[error] Command 'go test -count=1 ./proxy/...' failed during 'make test-all'.

🪛 GitHub Actions: Windows CI
proxy/process.go

[error] 447-447: Runtime panic: invalid memory address or nil pointer dereference in reverse proxy handling during TestProcess_AutomaticallyStartsUpstream. (Test failure in 'make test-all')

Refactor manual HTTP proxying logic in Process.ProxyRequest to use the standard
library's httputil.ReverseProxy.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f0dc14 and 1a6c864.

📒 Files selected for processing (2)
  • proxy/config/config.go (2 hunks)
  • proxy/process.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • proxy/process.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Fix all staticcheck-reported issues in Go code

Files:

  • proxy/config/config.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: run-tests
  • GitHub Check: run-tests
🔇 Additional comments (1)
proxy/config/config.go (1)

6-6: LGTM!

The net/url import is correctly added to support URL validation.

Comment on lines +346 to +351
// Validate the proxy URL.
if _, err := url.Parse(modelConfig.Proxy); err != nil {
return Config{}, fmt.Errorf(
"model %s: invalid proxy URL: %w", modelId, err,
)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify if stricter URL validation is needed.

The validation correctly catches URL parse errors. However, url.Parse is permissive and accepts empty strings, relative URLs, and URLs without scheme or host. Since the PR introduces httputil.ReverseProxy, which typically requires complete URLs with scheme and host, verify whether additional validation is needed.

Run the following script to check how the reverse proxy handles the parsed URL:


🏁 Script executed:

#!/bin/bash
# Description: Check if reverse proxy validates URL structure (scheme/host)
# Expected: Find validation or error handling for incomplete URLs

# Search for reverse proxy setup and URL usage
ast-grep --pattern 'reverseProxy = &httputil.ReverseProxy{$$$}'

# Search for proxy URL validation in process.go
rg -n --type=go -C5 'modelConfig.Proxy|ProxyURL' proxy/process.go

Length of output: 0


🏁 Script executed:

#!/bin/bash
echo "Searching for NewSingleHostReverseProxy usage..."
rg -nP 'NewSingleHostReverseProxy' -tgo -C3

echo "Searching for ReverseProxy struct literal..."
rg -nP '&httputil.ReverseProxy' -tgo -C3

echo "Searching for modelConfig.Proxy usage..."
rg -n 'modelConfig.Proxy' -tgo -C5

Length of output: 4449


Enforce complete proxy URL validation
After parsing, ensure both u.Scheme and u.Host are non-empty (e.g.

u, err := url.Parse(modelConfig.Proxy)
if err != nil || u.Scheme == "" || u.Host == "" {
    return Config{}, fmt.Errorf("model %s: proxy must include scheme and host", modelId)
}
```)

<details>
<summary>🤖 Prompt for AI Agents</summary>

In proxy/config/config.go around lines 346 to 351, the URL validation only
checks parse error and may accept incomplete URLs; update the logic to parse the
proxy into u and treat it as invalid if err != nil or u.Scheme == "" or u.Host
== "", returning a formatted error like "model %s: proxy must include scheme and
host" with modelId and the underlying error when present; ensure you use the
parsed u variable (not the raw string) for these checks and preserve existing
error-wrapping semantics.


</details>

<!-- This is an auto-generated comment by CodeRabbit -->

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
proxy/process_test.go (1)

439-441: LGTM with optional suggestion for test robustness.

The assertion correctly verifies that the full message was not delivered due to the upstream kill. The approach is reasonable given the non-deterministic timing of when the kill occurs during the response.

Optional: Consider adding an additional assertion to verify the response is either empty or a prefix of "12345" to more precisely capture the expected partial-response behavior:

 // Upstream may be killed mid-response.
 // Assert an incomplete or partial response.
 assert.NotEqual(t, "12345", w.Body.String())
+// Verify it's either empty or a valid prefix
+body := w.Body.String()
+if body != "" {
+	assert.True(t, strings.HasPrefix("12345", body), 
+		"partial response should be a prefix of '12345', got: %s", body)
+}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a6c864 and d3882e2.

📒 Files selected for processing (2)
  • proxy/process_test.go (1 hunks)
  • proxy/proxymanager_test.go (26 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Fix all staticcheck-reported issues in Go code

Files:

  • proxy/proxymanager_test.go
  • proxy/process_test.go
🔇 Additional comments (2)
proxy/proxymanager_test.go (2)

24-48: Well-structured test utility for streaming support.

The TestResponseRecorder correctly implements http.CloseNotifier to enable testing of streaming behavior with httputil.ReverseProxy. The buffered channel and helper methods are appropriately designed.

Note: While http.CloseNotifier was deprecated in Go 1.7 in favor of Request.Context() cancellation, it remains necessary for compatibility with httputil.ReverseProxy's internal checks for this interface. Based on learnings.


66-66: LGTM! Tests properly updated for streaming support.

All test functions have been correctly migrated to use CreateTestResponseRecorder() instead of httptest.NewRecorder(). This ensures that the tests can properly handle streaming scenarios that rely on the CloseNotify interface, which is required by the new httputil.ReverseProxy integration.

Also applies to: 103-103, 145-145, 188-188, 241-241, 340-340, 416-416, 505-505, 510-510, 548-548, 556-556, 600-600, 618-618, 624-624, 676-676, 711-711, 745-745, 813-813, 841-841, 849-849, 870-870, 898-898, 929-929, 964-964, 996-996, 1017-1017, 1109-1109, 1138-1138

@dwrz
Copy link
Copy Markdown
Contributor Author

dwrz commented Oct 13, 2025

@mostlygeek -- I gave the tests a quick look. It looks like the refactor to httputil.ReverseProxy may have surfaced a few issues. I'll need to better understand how the process management works to resolve the remaining ones.

I ran tests with the Go race detector enabled: go test -race -v ./... and it surfaced a few data races. It may be worth adding the ability to build with the race detector in the Makefile for builds where we want to detect concurrency issues.

Here's the output I get on the main branch:

$ go test -race -v ./...
?       github.com/mostlygeek/llama-swap        [no test files]
=== RUN   TestDefaultPublish
--- PASS: TestDefaultPublish (0.00s)
=== RUN   TestPublish
--- PASS: TestPublish (0.00s)
=== RUN   TestUnsubscribe
--- PASS: TestUnsubscribe (0.00s)
=== RUN   TestConcurrent
--- PASS: TestConcurrent (0.49s)
=== RUN   TestSubscribeDifferentType
--- PASS: TestSubscribeDifferentType (0.00s)
=== RUN   TestPublishDifferentType
--- PASS: TestPublishDifferentType (0.00s)
=== RUN   TestCloseDispatcher
--- PASS: TestCloseDispatcher (0.00s)
=== RUN   TestMatrix
=== RUN   TestMatrix/1x1
=== RUN   TestMatrix/10x1
=== RUN   TestMatrix/1x10
=== RUN   TestMatrix/10x10
=== RUN   TestMatrix/1x100
=== RUN   TestMatrix/10x100
--- PASS: TestMatrix (0.24s)
    --- PASS: TestMatrix/1x1 (0.00s)
    --- PASS: TestMatrix/10x1 (0.01s)
    --- PASS: TestMatrix/1x10 (0.00s)
    --- PASS: TestMatrix/10x10 (0.02s)
    --- PASS: TestMatrix/1x100 (0.02s)
    --- PASS: TestMatrix/10x100 (0.18s)
=== RUN   TestConcurrentSubscriptionRace
--- PASS: TestConcurrentSubscriptionRace (0.06s)
=== RUN   TestConcurrentHandlerRegistration
=== RUN   TestConcurrentHandlerRegistration/SameEventType
=== RUN   TestConcurrentHandlerRegistration/DifferentEventTypes
--- PASS: TestConcurrentHandlerRegistration (0.02s)
    --- PASS: TestConcurrentHandlerRegistration/SameEventType (0.01s)
    --- PASS: TestConcurrentHandlerRegistration/DifferentEventTypes (0.01s)
=== RUN   TestBackpressure
    event_test.go:298: Events processed: 1000/1000
--- PASS: TestBackpressure (0.10s)
PASS
ok      github.com/mostlygeek/llama-swap/event  (cached)
?       github.com/mostlygeek/llama-swap/misc/benchmark-chatcompletion  [no test files]
?       github.com/mostlygeek/llama-swap/misc/process-cmd-test  [no test files]
?       github.com/mostlygeek/llama-swap/misc/simple-responder  [no test files]
=== RUN   TestLogMonitor
--- PASS: TestLogMonitor (0.00s)
=== RUN   TestWrite_ImmutableBuffer
--- PASS: TestWrite_ImmutableBuffer (0.00s)
=== RUN   TestProcess_AutomaticallyStartsUpstream
--- PASS: TestProcess_AutomaticallyStartsUpstream (0.51s)
=== RUN   TestProcess_WaitOnMultipleStarts
==================
WARNING: DATA RACE
Write at 0x00c000103148 by goroutine 55:
  runtime.racewrite()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:180 +0x25c
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:82 +0x22f
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:85 +0x41

Previous read at 0x00c000103148 by goroutine 57:
  runtime.raceread()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:194 +0x58b
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:82 +0x22f
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:85 +0x41

Goroutine 55 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:78 +0x584
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 57 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:78 +0x584
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Write at 0x00c0001030f0 by goroutine 54:
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest.func2()
      /home/dwrz/projects/llama-swap/proxy/process.go:422 +0x4f
  runtime.deferreturn()
      /usr/lib/go/src/runtime/panic.go:589 +0x5d
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:82 +0x22f
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:85 +0x41

Previous write at 0x00c0001030f0 by goroutine 57:
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest.func2()
      /home/dwrz/projects/llama-swap/proxy/process.go:422 +0x4f
  runtime.deferreturn()
      /usr/lib/go/src/runtime/panic.go:589 +0x5d
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:82 +0x22f
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:85 +0x41

Goroutine 54 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:78 +0x584
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 57 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_WaitOnMultipleStarts()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:78 +0x584
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_WaitOnMultipleStarts (0.25s)
=== RUN   TestProcess_BrokenModelConfig
--- PASS: TestProcess_BrokenModelConfig (0.00s)
=== RUN   TestProcess_UnloadAfterTTL
    process_test.go:137: sending slow first request (4 seconds)
    process_test.go:143: sending second request (1 second)
==================
WARNING: DATA RACE
Read at 0x00c0001039f8 by goroutine 88:
  runtime.raceread()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:420 +0x1ed
  github.com/mostlygeek/llama-swap/proxy.TestProcess_UnloadAfterTTL()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:146 +0xca7
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c0001039f8 by goroutine 97:
  runtime.racewrite()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.func1()
      /home/dwrz/projects/llama-swap/proxy/process.go:289 +0x104

Goroutine 88 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 97 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:280 +0x165d
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_UnloadAfterTTL()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:135 +0x86f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Write at 0x00c0001039b0 by goroutine 88:
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest.func2()
      /home/dwrz/projects/llama-swap/proxy/process.go:422 +0x4f
  runtime.deferreturn()
      /usr/lib/go/src/runtime/panic.go:589 +0x5d
  github.com/mostlygeek/llama-swap/proxy.TestProcess_UnloadAfterTTL()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:146 +0xca7
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous read at 0x00c0001039b0 by goroutine 97:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.func1()
      /home/dwrz/projects/llama-swap/proxy/process.go:291 +0x119

Goroutine 88 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 97 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:280 +0x165d
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_UnloadAfterTTL()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:135 +0x86f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    process_test.go:152: sleep 5 seconds and check if unloaded
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_UnloadAfterTTL (10.26s)
=== RUN   TestProcess_LowTTLValue
    process_test.go:159: skipping test, edit process_test.go to run it
--- SKIP: TestProcess_LowTTLValue (0.00s)
=== RUN   TestProcess_HTTPRequestsHaveTimeToFinish
==================
WARNING: DATA RACE
Write at 0x00c000602c08 by goroutine 106:
  runtime.racewrite()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:180 +0x25c
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:215 +0x2b8
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:225 +0x4f

Previous read at 0x00c000602c08 by goroutine 104:
  runtime.raceread()
      <autogenerated>:1 +0x1e
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:194 +0x58b
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:215 +0x2b8
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:225 +0x4f

Goroutine 106 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:208 +0x7cc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 104 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:208 +0x7cc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c000602be0 by goroutine 107:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).Stop()
      /home/dwrz/projects/llama-swap/proxy/process.go:310 +0x2e
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:231 +0x53

Previous write at 0x00c000602be0 by goroutine 110:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 107 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:229 +0xb2a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 110 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:215 +0x2b8
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:225 +0x4f
==================
==================
WARNING: DATA RACE
Write at 0x00c000602bb0 by goroutine 105:
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest.func2()
      /home/dwrz/projects/llama-swap/proxy/process.go:422 +0x4f
  runtime.deferreturn()
      /usr/lib/go/src/runtime/panic.go:589 +0x5d
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:215 +0x2b8
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:225 +0x4f

Previous write at 0x00c000602bb0 by goroutine 104:
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest.func2()
      /home/dwrz/projects/llama-swap/proxy/process.go:422 +0x4f
  runtime.deferreturn()
      /usr/lib/go/src/runtime/panic.go:589 +0x5d
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:215 +0x2b8
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:225 +0x4f

Goroutine 105 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:208 +0x7cc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 104 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_HTTPRequestsHaveTimeToFinish()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:208 +0x7cc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    process_test.go:218: Expected status OK, got 502 for key 12345
    process_test.go:218: Expected status OK, got 502 for key fghij
    process_test.go:218: Expected status OK, got 502 for key abcde
    process_test.go:237:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/process_test.go:237
                Error:          Not equal:
                                expected: "12345"
                                actual  : "unable to start process: upstream command exited prematurely but successfully\n"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1,2 @@
                                -12345
                                +unable to start process: upstream command exited prematurely but successfully
                                +
                Test:           TestProcess_HTTPRequestsHaveTimeToFinish
    process_test.go:237:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/process_test.go:237
                Error:          Not equal:
                                expected: "abcde"
                                actual  : "unable to start process: process was already starting but wound up in state stopped\n"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1,2 @@
                                -abcde
                                +unable to start process: process was already starting but wound up in state stopped
                                +
                Test:           TestProcess_HTTPRequestsHaveTimeToFinish
    process_test.go:237:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/process_test.go:237
                Error:          Not equal:
                                expected: "fghij"
                                actual  : "unable to start process: process was already starting but wound up in state stopped\n"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1,2 @@
                                -fghij
                                +unable to start process: process was already starting but wound up in state stopped
                                +
                Test:           TestProcess_HTTPRequestsHaveTimeToFinish
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_HTTPRequestsHaveTimeToFinish (0.25s)
=== RUN   TestProcess_SwapState
=== RUN   TestProcess_SwapState/Stopped_to_Starting
=== RUN   TestProcess_SwapState/Starting_to_Ready
=== RUN   TestProcess_SwapState/Starting_to_Stopping
=== RUN   TestProcess_SwapState/Starting_to_Stopped
=== RUN   TestProcess_SwapState/Ready_to_Stopping
=== RUN   TestProcess_SwapState/Stopping_to_Stopped
=== RUN   TestProcess_SwapState/Stopping_to_Shutdown
=== RUN   TestProcess_SwapState/Stopped_to_Ready
=== RUN   TestProcess_SwapState/Ready_to_Starting
=== RUN   TestProcess_SwapState/Stopping_to_Ready
=== RUN   TestProcess_SwapState/Shutdown_to_Stopped
=== RUN   TestProcess_SwapState/Shutdown_to_Starting
=== RUN   TestProcess_SwapState/Expected_state_mismatch
--- PASS: TestProcess_SwapState (0.00s)
    --- PASS: TestProcess_SwapState/Stopped_to_Starting (0.00s)
    --- PASS: TestProcess_SwapState/Starting_to_Ready (0.00s)
    --- PASS: TestProcess_SwapState/Starting_to_Stopping (0.00s)
    --- PASS: TestProcess_SwapState/Starting_to_Stopped (0.00s)
    --- PASS: TestProcess_SwapState/Ready_to_Stopping (0.00s)
    --- PASS: TestProcess_SwapState/Stopping_to_Stopped (0.00s)
    --- PASS: TestProcess_SwapState/Stopping_to_Shutdown (0.00s)
    --- PASS: TestProcess_SwapState/Stopped_to_Ready (0.00s)
    --- PASS: TestProcess_SwapState/Ready_to_Starting (0.00s)
    --- PASS: TestProcess_SwapState/Stopping_to_Ready (0.00s)
    --- PASS: TestProcess_SwapState/Shutdown_to_Stopped (0.00s)
    --- PASS: TestProcess_SwapState/Shutdown_to_Starting (0.00s)
    --- PASS: TestProcess_SwapState/Expected_state_mismatch (0.00s)
=== RUN   TestProcess_ShutdownInterruptsHealthCheck
==================
WARNING: DATA RACE
Read at 0x00c0006c1d60 by goroutine 126:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.TestProcess_ShutdownInterruptsHealthCheck()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:315 +0x729
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c0006c1d60 by goroutine 127:
  github.com/mostlygeek/llama-swap/proxy.(*Process).Shutdown()
      /home/dwrz/projects/llama-swap/proxy/process.go:347 +0xef
  github.com/mostlygeek/llama-swap/proxy.TestProcess_ShutdownInterruptsHealthCheck.func1()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:310 +0xa4

Goroutine 126 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 127 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProcess_ShutdownInterruptsHealthCheck()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:307 +0x70a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_ShutdownInterruptsHealthCheck (1.25s)
=== RUN   TestProcess_ExitInterruptsHealthCheck
==================
WARNING: DATA RACE
Write at 0x00c000802f60 by goroutine 141:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Previous read at 0x00c000802f60 by goroutine 138:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.TestProcess_ExitInterruptsHealthCheck()      /home/dwrz/projects/llama-swap/proxy/process_test.go:337 +0x592
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 141 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.TestProcess_ExitInterruptsHealthCheck()      /home/dwrz/projects/llama-swap/proxy/process_test.go:337 +0x592
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 138 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171
==================
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_ExitInterruptsHealthCheck (1.25s)
=== RUN   TestProcess_ConcurrencyLimit
--- PASS: TestProcess_ConcurrencyLimit (0.63s)
=== RUN   TestProcess_StopImmediately
--- PASS: TestProcess_StopImmediately (0.25s)
=== RUN   TestProcess_ForceStopWithKill
--- PASS: TestProcess_ForceStopWithKill (1.25s)
=== RUN   TestProcess_StopCmd
--- PASS: TestProcess_StopCmd (0.25s)
=== RUN   TestProcess_EnvironmentSetCorrectly
==================
WARNING: DATA RACE
Read at 0x00c000602a20 by goroutine 193:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.TestProcess_EnvironmentSetCorrectly()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:487 +0xb24
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000602a20 by goroutine 203:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 193 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 203 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.TestProcess_EnvironmentSetCorrectly()
      /home/dwrz/projects/llama-swap/proxy/process_test.go:487 +0xb24
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    testing.go:1617: race detected during execution of test
--- FAIL: TestProcess_EnvironmentSetCorrectly (0.50s)
=== RUN   TestProcessGroup_DefaultHasCorrectModel
--- PASS: TestProcessGroup_DefaultHasCorrectModel (0.00s)
=== RUN   TestProcessGroup_HasMember
--- PASS: TestProcessGroup_HasMember (0.00s)
=== RUN   TestProcessGroup_ProxyRequestSwapIsTrueParallel
--- PASS: TestProcessGroup_ProxyRequestSwapIsTrueParallel (1.26s)
=== RUN   TestProcessGroup_ProxyRequestSwapIsFalse
=== RUN   TestProcessGroup_ProxyRequestSwapIsFalse/model3
=== RUN   TestProcessGroup_ProxyRequestSwapIsFalse/model4
--- PASS: TestProcessGroup_ProxyRequestSwapIsFalse (0.51s)
    --- PASS: TestProcessGroup_ProxyRequestSwapIsFalse/model3 (0.25s)
    --- PASS: TestProcessGroup_ProxyRequestSwapIsFalse/model4 (0.25s)
=== RUN   TestProxyManager_SwapProcessCorrectly
==================
WARNING: DATA RACE
Read at 0x00c0005834a0 by goroutine 299:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x72f
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapProcessCorrectly()      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:42 +0x6fc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c0005834a0 by goroutine 302:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 299 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 302 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x72f
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapProcessCorrectly()      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:42 +0x6fc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    proxymanager_test.go:43:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:43
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_SwapProcessCorrectly
    proxymanager_test.go:44:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:44
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model1"
                Test:           TestProxyManager_SwapProcessCorrectly
    proxymanager_test.go:43:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:43
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_SwapProcessCorrectly
    proxymanager_test.go:44:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:44
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model2"
                Test:           TestProxyManager_SwapProcessCorrectly
    testing.go:1617: race detected during execution of test
--- FAIL: TestProxyManager_SwapProcessCorrectly (0.51s)
=== RUN   TestProxyManager_SwapMultiProcess
=== RUN   TestProxyManager_SwapMultiProcess/model1
==================
WARNING: DATA RACE
Read at 0x00c0005839e0 by goroutine 310:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x2f3
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcess.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:79 +0x2c9
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c0005839e0 by goroutine 313:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 310 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcess()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:74 +0x584
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 313 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x2f3
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcess.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:79 +0x2c9
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    proxymanager_test.go:80:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:80
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_SwapMultiProcess/model1
    proxymanager_test.go:81:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:81
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model1"
                Test:           TestProxyManager_SwapMultiProcess/model1
    testing.go:1617: race detected during execution of test
=== RUN   TestProxyManager_SwapMultiProcess/model2
    proxymanager_test.go:80:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:80
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_SwapMultiProcess/model2
    proxymanager_test.go:81:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:81
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model2"
                Test:           TestProxyManager_SwapMultiProcess/model2
=== NAME  TestProxyManager_SwapMultiProcess
    proxymanager_test.go:86:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:86
                Error:          Not equal:
                                expected: "stopped"
                                actual  : "ready"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,2 +1,2 @@
                                -(proxy.ProcessState) (len=7) "stopped"
                                +(proxy.ProcessState) (len=5) "ready"

                Test:           TestProxyManager_SwapMultiProcess
    proxymanager_test.go:87:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:87
                Error:          Not equal:
                                expected: "stopped"
                                actual  : "ready"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,2 +1,2 @@
                                -(proxy.ProcessState) (len=7) "stopped"
                                +(proxy.ProcessState) (len=5) "ready"

                Test:           TestProxyManager_SwapMultiProcess
--- FAIL: TestProxyManager_SwapMultiProcess (0.51s)
    --- FAIL: TestProxyManager_SwapMultiProcess/model1 (0.25s)
    --- FAIL: TestProxyManager_SwapMultiProcess/model2 (0.25s)
=== RUN   TestProxyManager_PersistentGroupsAreNotSwapped
==================
WARNING: DATA RACE
Read at 0x00c000803f20 by goroutine 323:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x82f
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_PersistentGroupsAreNotSwapped()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:121 +0x7fc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000803f20 by goroutine 326:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 323 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 326 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x82f
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_PersistentGroupsAreNotSwapped()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:121 +0x7fc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    proxymanager_test.go:122:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:122
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    proxymanager_test.go:123:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:123
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model2"
                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    proxymanager_test.go:122:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:122
                Error:          Not equal:
                                expected: 200
                                actual  : 502
                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    proxymanager_test.go:123:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:123
                Error:          "unable to start process: upstream command exited prematurely but successfully\n" does not contain "model1"
                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    proxymanager_test.go:126:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:126
                Error:          Not equal:
                                expected: "stopped"
                                actual  : "ready"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,2 +1,2 @@
                                -(proxy.ProcessState) (len=7) "stopped"
                                +(proxy.ProcessState) (len=5) "ready"

                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    proxymanager_test.go:127:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:127
                Error:          Not equal:
                                expected: "stopped"
                                actual  : "ready"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,2 +1,2 @@
                                -(proxy.ProcessState) (len=7) "stopped"
                                +(proxy.ProcessState) (len=5) "ready"

                Test:           TestProxyManager_PersistentGroupsAreNotSwapped
    testing.go:1617: race detected during execution of test
--- FAIL: TestProxyManager_PersistentGroupsAreNotSwapped (0.51s)
=== RUN   TestProxyManager_SwapMultiProcessParallelRequests
==================
WARNING: DATA RACE
Read at 0x00c0004c9d60 by goroutine 339:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x3bd
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcessParallelRequests.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:164 +0x38d
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcessParallelRequests.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:177 +0x4f

Previous write at 0x00c0004c9d60 by goroutine 351:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 339 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcessParallelRequests()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:157 +0x5a4
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 351 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x3bd
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcessParallelRequests.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:164 +0x38d
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_SwapMultiProcessParallelRequests.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:177 +0x4f
==================
    proxymanager_test.go:167: Expected status OK, got 502 for key model1
    proxymanager_test.go:172:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:172
                                                        /usr/lib/go/src/runtime/asm_amd64.s:1693
                Error:          Received unexpected error:
                                invalid character 'u' looking for beginning of value
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    proxymanager_test.go:174:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:174
                                                        /usr/lib/go/src/runtime/asm_amd64.s:1693
                Error:          Not equal:
                                expected: false
                                actual  : true
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    proxymanager_test.go:167: Expected status OK, got 502 for key model2
    proxymanager_test.go:172:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:172
                                                        /usr/lib/go/src/runtime/asm_amd64.s:1693
                Error:          Received unexpected error:
                                invalid character 'u' looking for beginning of value
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    proxymanager_test.go:174:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:174
                                                        /usr/lib/go/src/runtime/asm_amd64.s:1693
                Error:          Not equal:
                                expected: false
                                actual  : true
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    proxymanager_test.go:186:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:186
                Error:          Not equal:
                                expected: "model1"
                                actual  : ""

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1 @@
                                -model1
                                +
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    proxymanager_test.go:186:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:186
                Error:          Not equal:
                                expected: "model2"
                                actual  : ""

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1 @@
                                -model2
                                +
                Test:           TestProxyManager_SwapMultiProcessParallelRequests
    testing.go:1617: race detected during execution of test
--- FAIL: TestProxyManager_SwapMultiProcessParallelRequests (1.76s)
=== RUN   TestProxyManager_ListModelsHandler
--- PASS: TestProxyManager_ListModelsHandler (0.00s)
=== RUN   TestProxyManager_ListModelsHandler_WithMetadata
--- PASS: TestProxyManager_ListModelsHandler_WithMetadata (0.00s)
=== RUN   TestProxyManager_ListModelsHandler_SortedByID
--- PASS: TestProxyManager_ListModelsHandler_SortedByID (0.00s)
=== RUN   TestProxyManager_Shutdown
==================
WARNING: DATA RACE
Read at 0x00c000583f20 by goroutine 363:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:83 +0x3f4
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x394
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Shutdown.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:454 +0x364
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Shutdown.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:457 +0x4f

Previous write at 0x00c000583f20 by goroutine 369:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 363 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Shutdown()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:447 +0x6dc
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 369 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:83 +0x3f4
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x394
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Shutdown.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:454 +0x364
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Shutdown.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:457 +0x4f
==================
    testing.go:1617: race detected during execution of test
--- FAIL: TestProxyManager_Shutdown (5.26s)
=== RUN   TestProxyManager_Unload
==================
WARNING: DATA RACE
Read at 0x00c000603ba0 by goroutine 400:
  github.com/mostlygeek/llama-swap/proxy.(*Process).CurrentState()
      /home/dwrz/projects/llama-swap/proxy/process.go:158 +0x9b
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:249 +0x1872
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x4bb
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Unload()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:480 +0x48b
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000603ba0 by goroutine 403:
  github.com/mostlygeek/llama-swap/proxy.(*Process).waitForCmd()
      /home/dwrz/projects/llama-swap/proxy/process.go:526 +0xa47
  github.com/mostlygeek/llama-swap/proxy.(*Process).start.gowrap2()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x33

Goroutine 400 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:2477 +0x85
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:2475 +0x96c
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:2337 +0xed4
  github.com/mostlygeek/llama-swap/proxy.TestMain()
      /home/dwrz/projects/llama-swap/proxy/helpers_test.go:44 +0x204
  main.main()
      _testmain.go:135 +0x171

Goroutine 403 (finished) created at:
  github.com/mostlygeek/llama-swap/proxy.(*Process).start()
      /home/dwrz/projects/llama-swap/proxy/process.go:225 +0x1275
  github.com/mostlygeek/llama-swap/proxy.(*Process).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/process.go:429 +0x2a4
  github.com/mostlygeek/llama-swap/proxy.(*ProcessGroup).ProxyRequest()
      /home/dwrz/projects/llama-swap/proxy/processgroup.go:73 +0x309
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:525 +0xea9
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).proxyOAIHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x8c
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.MetricsMiddleware.func8()
      /home/dwrz/projects/llama-swap/proxy/metrics_middleware.go:56 +0x55c
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x4bb
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_Unload()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:480 +0x48b
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    proxymanager_test.go:482:
                Error Trace:    /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:482
                Error:          Not equal:
                                expected: "stopped"
                                actual  : "ready"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1,2 +1,2 @@
                                -(proxy.ProcessState) (len=7) "stopped"
                                +(proxy.ProcessState) (len=5) "ready"

                Test:           TestProxyManager_Unload
    testing.go:1617: race detected during execution of test
--- FAIL: TestProxyManager_Unload (0.25s)
=== RUN   TestProxyManager_UnloadSingleModel
--- PASS: TestProxyManager_UnloadSingleModel (0.51s)
=== RUN   TestProxyManager_RunningEndpoint
=== RUN   TestProxyManager_RunningEndpoint/no_models_loaded
=== RUN   TestProxyManager_RunningEndpoint/single_model_loaded
--- PASS: TestProxyManager_RunningEndpoint (0.25s)
    --- PASS: TestProxyManager_RunningEndpoint/no_models_loaded (0.00s)
    --- PASS: TestProxyManager_RunningEndpoint/single_model_loaded (0.25s)
=== RUN   TestProxyManager_AudioTranscriptionHandler
--- PASS: TestProxyManager_AudioTranscriptionHandler (0.25s)
=== RUN   TestProxyManager_UseModelName
=== RUN   TestProxyManager_UseModelName/useModelName_over_rides_requested_model:_/v1/chat/completions
=== RUN   TestProxyManager_UseModelName/useModelName_over_rides_requested_model:_/v1/audio/transcriptions
--- PASS: TestProxyManager_UseModelName (0.25s)
    --- PASS: TestProxyManager_UseModelName/useModelName_over_rides_requested_model:_/v1/chat/completions (0.25s)
    --- PASS: TestProxyManager_UseModelName/useModelName_over_rides_requested_model:_/v1/audio/transcriptions (0.00s)
=== RUN   TestProxyManager_CORSOptionsHandler
=== RUN   TestProxyManager_CORSOptionsHandler/OPTIONS_with_no_headers
=== RUN   TestProxyManager_CORSOptionsHandler/OPTIONS_with_specific_headers
=== RUN   TestProxyManager_CORSOptionsHandler/Non-OPTIONS_request
--- PASS: TestProxyManager_CORSOptionsHandler (0.01s)
    --- PASS: TestProxyManager_CORSOptionsHandler/OPTIONS_with_no_headers (0.00s)
    --- PASS: TestProxyManager_CORSOptionsHandler/OPTIONS_with_specific_headers (0.00s)
    --- PASS: TestProxyManager_CORSOptionsHandler/Non-OPTIONS_request (0.00s)
=== RUN   TestProxyManager_Upstream
=== RUN   TestProxyManager_Upstream/main_model_name
=== RUN   TestProxyManager_Upstream/model_alias
--- PASS: TestProxyManager_Upstream (0.26s)
    --- PASS: TestProxyManager_Upstream/main_model_name (0.25s)
    --- PASS: TestProxyManager_Upstream/model_alias (0.00s)
=== RUN   TestProxyManager_ChatContentLength
--- PASS: TestProxyManager_ChatContentLength (0.25s)
=== RUN   TestProxyManager_FiltersStripParams
--- PASS: TestProxyManager_FiltersStripParams (0.25s)
=== RUN   TestProxyManager_MiddlewareWritesMetrics_NonStreaming
--- PASS: TestProxyManager_MiddlewareWritesMetrics_NonStreaming (0.26s)
=== RUN   TestProxyManager_MiddlewareWritesMetrics_Streaming
--- PASS: TestProxyManager_MiddlewareWritesMetrics_Streaming (0.26s)
=== RUN   TestProxyManager_HealthEndpoint
--- PASS: TestProxyManager_HealthEndpoint (0.00s)
=== RUN   TestProxyManager_CompletionEndpoint
--- PASS: TestProxyManager_CompletionEndpoint (0.25s)
=== RUN   TestProxyManager_StartupHooks
--- PASS: TestProxyManager_StartupHooks (0.51s)
=== RUN   TestProxyManager_StreamingEndpointsReturnNoBufferingHeader
=== RUN   TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//api/events==================
WARNING: DATA RACE
Read at 0x00c00039a7c0 by goroutine 640:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1090 +0x404
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c00039a7c0 by goroutine 641:
  net/http/httptest.(*ResponseRecorder).WriteHeader()
      /usr/lib/go/src/net/http/httptest/recorder.go:149 +0x91
  github.com/gin-gonic/gin.(*responseWriter).WriteHeaderNow()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/response_writer.go:77 +0x9b
  github.com/gin-gonic/gin.(*responseWriter).WriteString()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/response_writer.go:89 +0x3b
  github.com/gin-contrib/sse.writeEvent()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-contrib/sse@v0.1.0/sse-encoder.go:59 +0x55
  github.com/gin-contrib/sse.Encode()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-contrib/sse@v0.1.0/sse-encoder.go:44 +0xf3
  github.com/gin-contrib/sse.Event.Render()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-contrib/sse@v0.1.0/sse-encoder.go:91 +0x171
  github.com/gin-contrib/sse.(*Event).Render()
      <autogenerated>:1 +0xd4
  github.com/gin-gonic/gin.(*Context).Render()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:960 +0x10d
  github.com/gin-gonic/gin.(*Context).SSEvent()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:1108 +0x1124
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_api.go:194 +0x1053
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 640 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 641 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c00080f7a0 by goroutine 640:
  runtime.mapaccess1_faststr()
      /usr/lib/go/src/internal/runtime/maps/runtime_faststr_swiss.go:103 +0x0
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:34 +0x5e
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c00080f7a0 by goroutine 641:
  runtime.mapassign_faststr()
      /usr/lib/go/src/internal/runtime/maps/runtime_faststr_swiss.go:263 +0x0
  github.com/gin-contrib/sse.Event.WriteContentType()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-contrib/sse@v0.1.0/sse-encoder.go:96 +0x8d
  github.com/gin-contrib/sse.Event.Render()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-contrib/sse@v0.1.0/sse-encoder.go:90 +0xdd
  github.com/gin-contrib/sse.(*Event).Render()
      <autogenerated>:1 +0xd4
  github.com/gin-gonic/gin.(*Context).Render()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:960 +0x10d
  github.com/gin-gonic/gin.(*Context).SSEvent()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:1108 +0x1124
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_api.go:194 +0x1053
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 640 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 641 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c000a58fd8 by goroutine 640:
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:34 +0x68
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000a58fd8 by goroutine 641:
  net/textproto.MIMEHeader.Set()
      /usr/lib/go/src/net/textproto/header.go:22 +0x104
  net/http.Header.Set()
      /usr/lib/go/src/net/http/header.go:40 +0x71
  github.com/gin-gonic/gin.(*Context).Header()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:897 +0x49
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_api.go:107 +0xf1
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 640 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 641 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c000cfa690 by goroutine 640:
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:38 +0x90
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000cfa690 by goroutine 641:
  net/textproto.MIMEHeader.Set()
      /usr/lib/go/src/net/textproto/header.go:22 +0xa4
  net/http.Header.Set()
      /usr/lib/go/src/net/http/header.go:40 +0x71
  github.com/gin-gonic/gin.(*Context).Header()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:897 +0x49
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_api.go:107 +0xf1
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).apiSendEvents-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 640 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 641 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    testing.go:1617: race detected during execution of test
=== RUN   TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream
==================
WARNING: DATA RACE
Read at 0x00c000b5ba10 by goroutine 647:
  runtime.mapaccess1_faststr()
      /usr/lib/go/src/internal/runtime/maps/runtime_faststr_swiss.go:103 +0x0
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:34 +0x5e
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000b5ba10 by goroutine 648:
  runtime.mapassign_faststr()
      /usr/lib/go/src/internal/runtime/maps/runtime_faststr_swiss.go:263 +0x0
  net/textproto.MIMEHeader.Set()
      /usr/lib/go/src/net/textproto/header.go:22 +0xf4
  net/http.Header.Set()
      /usr/lib/go/src/net/http/header.go:40 +0x71
  github.com/gin-gonic/gin.(*Context).Header()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:897 +0x49
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_loghandlers.go:28 +0x5e
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 647 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 648 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c000a59270 by goroutine 647:
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:34 +0x68
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000a59270 by goroutine 648:
  net/textproto.MIMEHeader.Set()
      /usr/lib/go/src/net/textproto/header.go:22 +0x104
  net/http.Header.Set()
      /usr/lib/go/src/net/http/header.go:40 +0x71
  github.com/gin-gonic/gin.(*Context).Header()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:897 +0x49
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_loghandlers.go:32 +0xce
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 647 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 648 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
==================
WARNING: DATA RACE
Read at 0x00c000cfa960 by goroutine 647:
  net/textproto.MIMEHeader.Get()
      /usr/lib/go/src/net/textproto/header.go:38 +0x90
  net/http.Header.Get()
      /usr/lib/go/src/net/http/header.go:50 +0x4d4
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1091 +0x4be
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Previous write at 0x00c000cfa960 by goroutine 648:
  net/textproto.MIMEHeader.Set()
      /usr/lib/go/src/net/textproto/header.go:22 +0xa4
  net/http.Header.Set()
      /usr/lib/go/src/net/http/header.go:40 +0x71
  github.com/gin-gonic/gin.(*Context).Header()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:897 +0x49
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_loghandlers.go:32 +0xce
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).streamLogsHandler-fm()
      <autogenerated>:1 +0x3d
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x3cf
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func2()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:185 +0x261
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x1b5
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).setupGinEngine.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:144 +0x142
  github.com/gin-gonic/gin.(*Context).Next()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0xe47
  github.com/gin-gonic/gin.(*Engine).handleHTTPRequest()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x784
  github.com/gin-gonic/gin.(*Engine).ServeHTTP()
      /home/dwrz/.local/share/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x3e6
  github.com/mostlygeek/llama-swap/proxy.(*ProxyManager).ServeHTTP()
      /home/dwrz/projects/llama-swap/proxy/proxymanager.go:282 +0x76
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1.gowrap1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x17

Goroutine 647 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:1997 +0x9d2
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1077 +0x348
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44

Goroutine 648 (running) created at:
  github.com/mostlygeek/llama-swap/proxy.TestProxyManager_StreamingEndpointsReturnNoBufferingHeader.func1()
      /home/dwrz/projects/llama-swap/proxy/proxymanager_test.go:1087 +0x3ea
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:1934 +0x21c
  testing.(*T).Run.gowrap1()
      /usr/lib/go/src/testing/testing.go:1997 +0x44
==================
    testing.go:1617: race detected during execution of test
=== RUN   TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream/proxy
=== RUN   TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream/upstream
--- FAIL: TestProxyManager_StreamingEndpointsReturnNoBufferingHeader (0.04s)
    --- FAIL: TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//api/events (0.01s)
    --- FAIL: TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream (0.01s)
    --- PASS: TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream/proxy (0.01s)
    --- PASS: TestProxyManager_StreamingEndpointsReturnNoBufferingHeader//logs/stream/upstream (0.01s)
=== RUN   TestProxyManager_ProxiedStreamingEndpointReturnsNoBufferingHeader
--- PASS: TestProxyManager_ProxiedStreamingEndpointReturnsNoBufferingHeader (0.25s)
=== RUN   TestSanitizeAccessControlRequestHeaderValues
=== RUN   TestSanitizeAccessControlRequestHeaderValues/empty_string
=== RUN   TestSanitizeAccessControlRequestHeaderValues/whitespace_only
=== RUN   TestSanitizeAccessControlRequestHeaderValues/single_valid_value
=== RUN   TestSanitizeAccessControlRequestHeaderValues/multiple_valid_values
=== RUN   TestSanitizeAccessControlRequestHeaderValues/values_with_extra_spaces
=== RUN   TestSanitizeAccessControlRequestHeaderValues/values_with_tabs
=== RUN   TestSanitizeAccessControlRequestHeaderValues/values_with_invalid_characters
=== RUN   TestSanitizeAccessControlRequestHeaderValues/empty_values_in_list
=== RUN   TestSanitizeAccessControlRequestHeaderValues/leading_and_trailing_commas
=== RUN   TestSanitizeAccessControlRequestHeaderValues/mixed_valid_and_invalid_values
=== RUN   TestSanitizeAccessControlRequestHeaderValues/mixed_case_values
--- PASS: TestSanitizeAccessControlRequestHeaderValues (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/empty_string (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/whitespace_only (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/single_valid_value (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/multiple_valid_values (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/values_with_extra_spaces (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/values_with_tabs (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/values_with_invalid_characters (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/empty_values_in_list (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/leading_and_trailing_commas (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/mixed_valid_and_invalid_values (0.00s)
    --- PASS: TestSanitizeAccessControlRequestHeaderValues/mixed_case_values (0.00s)
FAIL
FAIL    github.com/mostlygeek/llama-swap/proxy  30.865s
=== RUN   TestConfig_SanitizeCommand
--- PASS: TestConfig_SanitizeCommand (0.00s)
=== RUN   TestConfig_DefaultValuesPosix
--- PASS: TestConfig_DefaultValuesPosix (0.00s)
=== RUN   TestConfig_LoadPosix
--- PASS: TestConfig_LoadPosix (0.00s)
=== RUN   TestConfig_GroupMemberIsUnique
--- PASS: TestConfig_GroupMemberIsUnique (0.00s)
=== RUN   TestConfig_ModelAliasesAreUnique
--- PASS: TestConfig_ModelAliasesAreUnique (0.00s)
=== RUN   TestConfig_FindConfig
--- PASS: TestConfig_FindConfig (0.00s)
=== RUN   TestConfig_AutomaticPortAssignments
=== RUN   TestConfig_AutomaticPortAssignments/Default_Port_Ranges
=== RUN   TestConfig_AutomaticPortAssignments/User_specific_port_ranges
=== RUN   TestConfig_AutomaticPortAssignments/Invalid_start_port
=== RUN   TestConfig_AutomaticPortAssignments/start_port_must_be_greater_than_1
=== RUN   TestConfig_AutomaticPortAssignments/Automatic_port_assignments
=== RUN   TestConfig_AutomaticPortAssignments/Proxy_value_required_if_no_${PORT}_in_cmd
--- PASS: TestConfig_AutomaticPortAssignments (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/Default_Port_Ranges (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/User_specific_port_ranges (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/Invalid_start_port (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/start_port_must_be_greater_than_1 (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/Automatic_port_assignments (0.00s)
    --- PASS: TestConfig_AutomaticPortAssignments/Proxy_value_required_if_no_${PORT}_in_cmd (0.00s)
=== RUN   TestConfig_MacroReplacement
--- PASS: TestConfig_MacroReplacement (0.00s)
=== RUN   TestConfig_MacroReservedNames
=== RUN   TestConfig_MacroReservedNames/global_macro_named_PORT
=== RUN   TestConfig_MacroReservedNames/global_macro_named_MODEL_ID
=== RUN   TestConfig_MacroReservedNames/model_macro_named_PORT
=== RUN   TestConfig_MacroReservedNames/model_macro_named_MODEL_ID
--- PASS: TestConfig_MacroReservedNames (0.00s)
    --- PASS: TestConfig_MacroReservedNames/global_macro_named_PORT (0.00s)
    --- PASS: TestConfig_MacroReservedNames/global_macro_named_MODEL_ID (0.00s)
    --- PASS: TestConfig_MacroReservedNames/model_macro_named_PORT (0.00s)
    --- PASS: TestConfig_MacroReservedNames/model_macro_named_MODEL_ID (0.00s)
=== RUN   TestConfig_MacroErrorOnUnknownMacros
=== RUN   TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_cmd
=== RUN   TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_cmdStop
=== RUN   TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_proxy
=== RUN   TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_checkEndpoint
=== RUN   TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_filters.stripParams
--- PASS: TestConfig_MacroErrorOnUnknownMacros (0.00s)
    --- PASS: TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_cmd (0.00s)
    --- PASS: TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_cmdStop (0.00s)
    --- PASS: TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_proxy (0.00s)
    --- PASS: TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_checkEndpoint (0.00s)
    --- PASS: TestConfig_MacroErrorOnUnknownMacros/unknown_macro_in_filters.stripParams (0.00s)
=== RUN   TestStripComments
=== RUN   TestStripComments/no_comments
=== RUN   TestStripComments/single_comment_line
=== RUN   TestStripComments/multiple_comment_lines
=== RUN   TestStripComments/comment_with_spaces
=== RUN   TestStripComments/empty_lines_preserved
=== RUN   TestStripComments/only_comments
=== RUN   TestStripComments/empty_string
--- PASS: TestStripComments (0.00s)
    --- PASS: TestStripComments/no_comments (0.00s)
    --- PASS: TestStripComments/single_comment_line (0.00s)
    --- PASS: TestStripComments/multiple_comment_lines (0.00s)
    --- PASS: TestStripComments/comment_with_spaces (0.00s)
    --- PASS: TestStripComments/empty_lines_preserved (0.00s)
    --- PASS: TestStripComments/only_comments (0.00s)
    --- PASS: TestStripComments/empty_string (0.00s)
=== RUN   TestConfig_MacroInCommentStrippedBeforeExpansion
--- PASS: TestConfig_MacroInCommentStrippedBeforeExpansion (0.00s)
=== RUN   TestConfig_MacroModelId
--- PASS: TestConfig_MacroModelId (0.00s)
=== RUN   TestConfig_TypedMacrosInMetadata
--- PASS: TestConfig_TypedMacrosInMetadata (0.00s)
=== RUN   TestConfig_NestedStructuresInMetadata
--- PASS: TestConfig_NestedStructuresInMetadata (0.00s)
=== RUN   TestConfig_ModelLevelMacroPrecedenceInMetadata
--- PASS: TestConfig_ModelLevelMacroPrecedenceInMetadata (0.00s)
=== RUN   TestConfig_UnknownMacroInMetadata
--- PASS: TestConfig_UnknownMacroInMetadata (0.00s)
=== RUN   TestConfig_InvalidMacroType
--- PASS: TestConfig_InvalidMacroType (0.00s)
=== RUN   TestConfig_MacroTypeValidation
=== RUN   TestConfig_MacroTypeValidation/string_macro
=== RUN   TestConfig_MacroTypeValidation/int_macro
=== RUN   TestConfig_MacroTypeValidation/float_macro
=== RUN   TestConfig_MacroTypeValidation/bool_macro
=== RUN   TestConfig_MacroTypeValidation/array_macro_(invalid)
=== RUN   TestConfig_MacroTypeValidation/map_macro_(invalid)
--- PASS: TestConfig_MacroTypeValidation (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/string_macro (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/int_macro (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/float_macro (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/bool_macro (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/array_macro_(invalid) (0.00s)
    --- PASS: TestConfig_MacroTypeValidation/map_macro_(invalid) (0.00s)
=== RUN   TestConfig_MacroInMacroBasic
--- PASS: TestConfig_MacroInMacroBasic (0.00s)
=== RUN   TestConfig_MacroInMacroLIFOOrder
--- PASS: TestConfig_MacroInMacroLIFOOrder (0.00s)
=== RUN   TestConfig_ModelIdInGlobalMacro
--- PASS: TestConfig_ModelIdInGlobalMacro (0.00s)
=== RUN   TestConfig_ModelMacroOverridesGlobal
--- PASS: TestConfig_ModelMacroOverridesGlobal (0.00s)
=== RUN   TestConfig_SelfReferenceDetection
--- PASS: TestConfig_SelfReferenceDetection (0.00s)
=== RUN   TestConfig_UndefinedMacroReference
--- PASS: TestConfig_UndefinedMacroReference (0.00s)
=== RUN   TestConfig_ModelConfigSanitizedCommand
--- PASS: TestConfig_ModelConfigSanitizedCommand (0.00s)
=== RUN   TestConfig_ModelFilters
=== RUN   TestConfig_ModelFilters/Testing_macros_in_filters_for_model_model1
=== RUN   TestConfig_ModelFilters/Testing_macros_in_filters_for_model_legacy
--- PASS: TestConfig_ModelFilters (0.00s)
    --- PASS: TestConfig_ModelFilters/Testing_macros_in_filters_for_model_model1 (0.00s)
    --- PASS: TestConfig_ModelFilters/Testing_macros_in_filters_for_model_legacy (0.00s)
PASS
ok      github.com/mostlygeek/llama-swap/proxy/config   1.013s
FAIL

@mostlygeek mostlygeek mentioned this pull request Oct 13, 2025
13 tasks
@mostlygeek
Copy link
Copy Markdown
Owner

@dwrz I opened #348 to track and fix the races.

@mostlygeek mostlygeek merged commit d58a8b8 into mostlygeek:main Oct 13, 2025
3 checks passed
@mostlygeek
Copy link
Copy Markdown
Owner

Thanks, looks good! Also all data races fixed in #349

@dwrz dwrz deleted the reverse-proxy branch October 14, 2025 12:19
mostlygeek added a commit that referenced this pull request Oct 26, 2025
Switching to use httputil.ReverseProxy in #342 introduced a possible
panic if a client disconnects while streaming the body. Since llama-swap
does not use http.Server the recover() is not automatically there.

- introduce a recover() in Process.ProxyRequest to recover and log the
  event
- add TestProcess_ReverseProxyPanicIsHandled to reproduce and test the
  fix

fixes: #362
mostlygeek added a commit that referenced this pull request Oct 26, 2025
Switching to use httputil.ReverseProxy in #342 introduced a possible
panic if a client disconnects while streaming the body. Since llama-swap
does not use http.Server the recover() is not automatically there.

- introduce a recover() in Process.ProxyRequest to recover and log the
  event
- add TestProcess_ReverseProxyPanicIsHandled to reproduce and test the
  fix

fixes: #362
0uep pushed a commit to lynxai-team/llama-swap that referenced this pull request Nov 21, 2025
Switching to use httputil.ReverseProxy in mostlygeek#342 introduced a possible
panic if a client disconnects while streaming the body. Since llama-swap
does not use http.Server the recover() is not automatically there.

- introduce a recover() in Process.ProxyRequest to recover and log the
  event
- add TestProcess_ReverseProxyPanicIsHandled to reproduce and test the
  fix

fixes: mostlygeek#362
rohitpaul pushed a commit to rohitpaul/llama-swap that referenced this pull request Mar 29, 2026
* Refactor to use httputil.ReverseProxy

Refactor manual HTTP proxying logic in Process.ProxyRequest to use the standard
library's httputil.ReverseProxy.

* Refactor TestProcess_ForceStopWithKill test

Update to handle behavior with httputil.ReverseProxy.

* Fix gin interface conversion panic
rohitpaul pushed a commit to rohitpaul/llama-swap that referenced this pull request Mar 29, 2026
Switching to use httputil.ReverseProxy in mostlygeek#342 introduced a possible
panic if a client disconnects while streaming the body. Since llama-swap
does not use http.Server the recover() is not automatically there.

- introduce a recover() in Process.ProxyRequest to recover and log the
  event
- add TestProcess_ReverseProxyPanicIsHandled to reproduce and test the
  fix

fixes: mostlygeek#362
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.

2 participants