gofiber/fiber · error
failed to unmarshal xml: %w
Error message
failed to unmarshal xml: %w
What it means
Returned by XMLBinding.Bind (binder/xml.go:22) when the configured XMLDecoder (by default encoding/xml.Unmarshal) fails to parse the request body into the target struct. Fiber wraps the underlying xml.Unmarshal error so callers see both the parse failure and the wrap context. It surfaces during BodyParser/Context binding when the Content-Type is application/xml or the XML binder is explicitly selected.
Source
Thrown at binder/xml.go:22
"fmt"
"github.com/gofiber/utils/v2"
)
// XMLBinding is the XML binder for XML request body.
type XMLBinding struct {
XMLDecoder utils.XMLUnmarshal
}
// Name returns the binding name.
func (*XMLBinding) Name() string {
return "xml"
}
// Bind parses the request body as XML and returns the result.
func (b *XMLBinding) Bind(body []byte, out any) error {
if err := b.XMLDecoder(body, out); err != nil {
return fmt.Errorf("failed to unmarshal xml: %w", err)
}
return nil
}
// Reset resets the XMLBinding binder.
func (b *XMLBinding) Reset() {
b.XMLDecoder = nil
}
View on GitHub (pinned to 9a4c7e57fe)
Solutions
- Validate the request body is well-formed XML (single root element, properly closed tags) before or right after parsing.
- Confirm struct fields carry correct xml:"..." tags matching the incoming element/attribute names.
- Check Content-Type and decompress/charset-convert the body before calling BodyParser if the client sends gzip or a non-UTF-8 encoding.
- Return a 400 with the wrapped error so clients can correct their payload.
Example fix
// before
if err := ctx.BodyParser(&payload); err != nil {
return err // opaque 500
}
// after — select XML explicitly and report a clear 400
if err := ctx.BodyParser(&payload); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid XML body: "+err.Error())
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the body is well-formed XML before binding.
func isWellFormedXML(body []byte) bool {
dec := xml.NewDecoder(bytes.NewReader(body))
for {
if _, err := dec.Token(); err == io.EOF {
return true
} else if err != nil {
return false
}
}
} Try / catch
if err := ctx.BodyParser(&payload); err != nil {
if strings.Contains(err.Error(), "failed to unmarshal xml") {
return fiber.NewError(fiber.StatusBadRequest, "malformed XML body")
}
return err
} Prevention
- Document and enforce the exact XML schema clients must send.
- Verify Content-Type matches application/xml before attempting XML binding.
- Decompress and charset-convert bodies before parsing when clients may send gzip or non-UTF-8 encodings.
- Always return 400 (not 500) for unmarshal failures so clients can fix their payload.
When it happens
Trigger: Calling app.BodyParser(ctx, &structPtr) on a request whose Content-Type is application/xml but whose body is malformed, truncated, uses attributes the struct cannot receive, or declares a different encoding (e.g. UTF-16 BOM). Also triggered by a charset declaration xml.Unmarshal cannot handle, or by a body that does not match the struct's xml tags.
Common situations: Client sends Content-Type: application/xml with a JSON body or plain text; the XML lacks a single root element; field names in the XML do not match the struct's xml:"name" tags; the body is gzip/compressed but not decoded first; version change where a field type changed and the old payload no longer unmarshals.
Related errors
- unsupported value type: %T
- fiber: failed to encode shared state %s value: %w
- fiber: failed to decode shared state %s value: %w
- fiber: failed to %s shared state %s value: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/9e5db863c6beef67.json.
Report an issue: GitHub.