Skip to content

πŸ› [Bug]: Panic when using fiber.Ctx as context.Context after upgrading v3 beta.4 β†’ v3.0.0-rc.1Β #3718

@gades

Description

@gades

Bug Description

Panic when using fiber.Ctx as context.Context after upgrading v3 beta.4 β†’ v3.0.0-rc.1

After migrating from v3 beta.4 (where we used c.Context()) to v3.0.0-rc.1 (where fiber.Ctx itself implements context.Context), our app randomly panics when fiber.Ctx is passed as a context.Context into code that continues running after the handler returns.
The crash typically appears after a handful of requests (e.g., 5–20), then intermittently every few requests.


Environment

  • Fiber: v3.0.0-rc.1
  • fasthttp: v1.65.0
  • Go: 1.25.0 (darwin/arm64)
  • OS: macOS

Actual Behavior

Intermittent panic (example):

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

goroutine 66 [running]:
github.com/valyala/fasthttp.(*RequestCtx).UserValue(...)
    .../github.com/valyala/fasthttp@v1.65.0/server.go:773
github.com/gofiber/fiber/v3.(*DefaultCtx).Value(0x100000000?, {0x1018c0320?, 0x1023b3d40?})
    .../github.com/gofiber/fiber/v3@v3.0.0-rc.1/ctx.go:382 +0x24
context.value({0x101a656a0?, 0x14000246140?}, {0x1018c0320, 0x1023b3d40})
    .../src/context/context.go:801 +0x230
context.(*cancelCtx).Value(0x1023b3d4e?, {0x1018c0320?, 0x1023b3d40?})
    .../src/context/context.go:445 +0x6c
net.(*sysDialer).dialSingle(0x140000d2000, {0x101a656a0, 0x140001525a0}, {0x101a61aa8, 0x1400014a0c0})
    .../src/net/dial.go:704 +0x5c
net.(*sysDialer).dialSerial(0x140000d2000, {0x101a656a0, 0x140001525a0}, {0x14000030470?, 0x1, 0x100c94130?})
    .../src/net/dial.go:686 +0x194
net.(*sysDialer).dialParallel.func1({0x101a656a0?, 0x140001525a0?}, 0x1)
    .../src/net/dial.go:606 +0x64
created by net.(*sysDialer).dialParallel in goroutine 35
    .../src/net/dial.go:621 +0x1b4

Analysis / Likely Root Cause

  • In v3.0.0-rc.1, fiber.Ctx implements context.Context and (*DefaultCtx).Value delegates to fasthttp.RequestCtx.UserValue.
  • After the handler returns, fiber.Ctx gets reused, and the underlying RequestCtx may be cleared or nil.
  • Any later call to ctx.Value(...) (e.g., in background goroutines or async client work) dereferences a nil pointer β†’ panic.
  • The intermittent nature suggests a race between handler completion and background work accessing ctx.Value(...).

Regression Note

This behavior surfaced after the migration beta.4 β†’ rc.1, when switching from c.Context() to using fiber.Ctx directly as context.Context. While this may be intended as a breaking change, the current behavior is surprising because it results in a panic instead of a safe no-op.

How to Reproduce


Steps to Reproduce (minimal)

    package main

    import (
        "context"
        "net/http"
        "time"

        "github.com/gofiber/fiber/v3"
    )

    func main() {
        app := fiber.New()

        app.Get("/", func(c fiber.Ctx) error {
            // IMPORTANT: pass fiber.Ctx as context.Context
            req, _ := http.NewRequest("GET", "http://example.com", nil)
            req = req.WithContext(c)

            client := &http.Client{Timeout: 5 * time.Second}

            // Run in a goroutine so it may outlive the handler
            go func() { _, _ = client.Do(req) }()

            return c.SendString("ok")
        })

        _ = app.Listen(":8080")
    }

Reproduce by sending multiple requests quickly (e.g., for i in {1..50}; do curl -s http://localhost:8080 >/dev/null; done).

Expected Behavior


Expected Behavior

  • Either using fiber.Ctx as context.Context should not panic even if referenced after the handler returns (at worst, Value/Done/Err return safe values),
    or
  • Provide/document a way to obtain a safe, detached std context.Context (a snapshot of user-values + cancellation) that can be passed outside the request lifetime.

Fiber Version

v3.0.0-rc.1

Code Snippet (optional)

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my problem prior to opening this one.
  • I understand that improperly formatted bug reports may be closed without explanation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions