Skip to content

BindStyledParameterWithOptions fails for label and matrix style primitive parameters #99

@mromaszewicz

Description

@mromaszewicz

Bug Description

BindStyledParameterWithOptions does not strip the style prefix when binding primitive (non-struct, non-slice, non-map) values with label or matrix styles. This causes server-side parameter binding to fail with parse errors for these style/type combinations.

Root Cause

In bindparam.go, BindStyledParameterWithOptions has three code paths:

  1. Struct/Map (line ~118): calls splitStyledParameter() which correctly strips style prefixes
  2. Slice (line ~129): calls splitStyledParameter() which correctly strips style prefixes
  3. Primitive (line ~156): calls BindStringToObject(value, dest) directly without stripping the style prefix

For simple and form styles, primitives have no prefix so this works fine. But for label and matrix styles, the styled value still contains its prefix when passed to BindStringToObject.

Reproduction

Label style

The client correctly serializes an int32 value 5 as .5 (per OpenAPI 3.0 label style). On the server:

```go
// value = ".5" (with leading dot)
BindStyledParameterWithOptions("label", "param", ".5", &dest, opts)
// Falls through to: BindStringToObject(".5", &int32)
// Error: strconv.ParseInt: parsing ".5": invalid syntax
```

Matrix style

The client serializes 5 as ;param=5. On the server:

```go
// value = ";param=5"
BindStyledParameterWithOptions("matrix", "param", ";param=5", &dest, opts)
// Falls through to: BindStringToObject(";param=5", &int32)
// Error: strconv.ParseInt: parsing ";param=5": invalid syntax
```

Why arrays/objects are unaffected

For arrays and objects, splitStyledParameter() is called, which correctly strips the . prefix (label) and ;name= prefix (matrix) before binding individual parts. The bug is only in the primitive code path which bypasses splitStyledParameter entirely.

Affected combinations

Style Explode Primitive Array Object
simple false OK OK OK
simple true OK OK OK
label false BROKEN OK OK
label true BROKEN OK OK
matrix false BROKEN OK OK
matrix true BROKEN OK OK

Suggested Fix

Before the final BindStringToObject(value, dest) call in BindStyledParameterWithOptions, strip the style prefix for primitive values:

```go
// Strip style prefix for primitive values.
switch style {
case "label":
if !strings.HasPrefix(value, ".") {
return fmt.Errorf("invalid format for label parameter '%s', should start with '.'", paramName)
}
value = value[1:]
case "matrix":
prefix := ";" + paramName + "="
if !strings.HasPrefix(value, prefix) {
return fmt.Errorf("expected parameter '%s' to start with %s", paramName, prefix)
}
value = strings.TrimPrefix(value, prefix)
}
return BindStringToObject(value, dest)
```

How this was discovered

While building a comprehensive parameter permutation test suite for oapi-codegen, testing every combination of parameter location x style x explode x value type (primitive, array, object) via client-to-server round-trips. The label and matrix primitive tests fail with 400 errors on the server side. The tests are currently skipped with a note referencing this bug.

Environment

  • github.com/oapi-codegen/runtime v1.2.0
  • Go 1.24
  • Tested with Echo server framework (but the bug is in the runtime library, framework-independent)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions