dd-trace-go icon indicating copy to clipboard operation
dd-trace-go copied to clipboard

[Bug] v2.3.0 gin contrib breaks builds with -tags nomsgpack

Open sdotson opened this issue 3 months ago • 1 comments

Description

The gin contrib package in dd-trace-go v2.3.0 fails to compile when building with the -tags nomsgpack build tag.

Environment

  • dd-trace-go version: v2.3.0
  • Go version: 1.24.0
  • Affected package: github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2

Steps to Reproduce

  1. Create a Go project that imports github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2
  2. Build with the nomsgpack tag:
    go build -tags nomsgpack ./...
    

Expected Behavior

The build should succeed. The gin framework supports the nomsgpack build tag to exclude msgpack support and reduce binary size by removing the heavy github.com/ugorji/go/codec dependency.

Actual Behavior

Build fails with compilation error:

# github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:54:17: cannot use AppsecBinding{…} (value of struct type AppsecBinding) as binding.jsonBinding value in assignment
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:55:16: cannot use AppsecBinding{…} (value of struct type AppsecBinding) as binding.xmlBinding value in assignment
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:56:21: cannot use AppsecBinding{…} (value of struct type AppsecBinding) as binding.protobufBinding value in assignment
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:57:10: undefined: binding.MsgPack
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:58:17: cannot use AppsecBinding{…} (value of struct type AppsecBinding) as binding.yamlBinding value in assignment
../../go/pkg/mod/github.com/!data!dog/dd-trace-go/contrib/gin-gonic/gin/[email protected]/appsec.go:59:17: cannot use AppsecBinding{…} (value of struct type AppsecBinding) as binding.tomlBinding value in assignment

Root Cause

The issue was introduced in v2.3.0 with the AppSec request body analysis feature (#3930). The appsec.go file unconditionally references binding.MsgPack in its init() function:

https://github.com/DataDog/dd-trace-go/blob/main/contrib/gin-gonic/gin/appsec.go#L51-L59

func init() {
    binding.JSON = AppsecBinding{BindingBody: binding.JSON}
    binding.XML = AppsecBinding{BindingBody: binding.XML}
    binding.ProtoBuf = AppsecBinding{BindingBody: binding.ProtoBuf}
    binding.MsgPack = AppsecBinding{BindingBody: binding.MsgPack}  // Line 57 - undefined when nomsgpack tag is used
    binding.YAML = AppsecBinding{BindingBody: binding.YAML}
    binding.TOML = AppsecBinding{BindingBody: binding.TOML}
}

When the nomsgpack build tag is active, gin's binding package doesn't define binding.MsgPack (see gin's binding_nomsgpack.go), causing the compilation error.

Proposed Solution

Add build tag guards to handle the msgpack binding conditionally. Here's a suggested approach:

appsec.go (default, with msgpack):

//go:build !nomsgpack

func init() {
    binding.JSON = AppsecBinding{BindingBody: binding.JSON}
    binding.XML = AppsecBinding{BindingBody: binding.XML}
    binding.ProtoBuf = AppsecBinding{BindingBody: binding.ProtoBuf}
    binding.MsgPack = AppsecBinding{BindingBody: binding.MsgPack}
    binding.YAML = AppsecBinding{BindingBody: binding.YAML}
    binding.TOML = AppsecBinding{BindingBody: binding.TOML}
}

appsec_nomsgpack.go (new file, without msgpack):

//go:build nomsgpack

func init() {
    binding.JSON = AppsecBinding{BindingBody: binding.JSON}
    binding.XML = AppsecBinding{BindingBody: binding.XML}
    binding.ProtoBuf = AppsecBinding{BindingBody: binding.ProtoBuf}
    // binding.MsgPack is not available with nomsgpack tag
    binding.YAML = AppsecBinding{BindingBody: binding.YAML}
    binding.TOML = AppsecBinding{BindingBody: binding.TOML}
}

Workaround

Until this is fixed, users can pin to v2.2.3 using replace directives in their go.mod:

replace (
    github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2 => github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2 v2.2.3
    github.com/DataDog/dd-trace-go/contrib/net/http/v2 => github.com/DataDog/dd-trace-go/contrib/net/http/v2 v2.2.3
    github.com/DataDog/dd-trace-go/v2 => github.com/DataDog/dd-trace-go/v2 v2.2.3
)

Impact

This affects any project using both:

  • dd-trace-go v2.3.0+ with gin contrib
  • The nomsgpack build tag (either explicitly or through dependencies)

This is a regression from v2.2.3, which builds successfully with the nomsgpack tag.

sdotson avatar Nov 11 '25 15:11 sdotson

Pinging @DataDog/asm-go so they can take a look. Thank you for the detailed report.

darccio avatar Nov 13 '25 08:11 darccio