netbirdio/netbird · error
failed to marshal response
Error message
failed to marshal response
What it means
HTTP 500 from respondGetRequest when json.Marshal of the GetURLResponse struct fails. The struct holds only two exported string fields (URL, Key), which json.Marshal cannot fail on today, so seeing this error implies a server regression: types.GetURLResponse gained an unmarshalable field (chan, func, or reference cycle).
Source
Thrown at upload-server/server/server.go:99
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return false
}
if r.Header.Get(types.ClientHeader) != types.ClientHeaderValue {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return false
}
return true
}
func respondGetRequest(w http.ResponseWriter, uploadURL string, objectKey string) {
response := types.GetURLResponse{
URL: uploadURL,
Key: objectKey,
}
rdata, err := json.Marshal(response)
if err != nil {
http.Error(w, "failed to marshal response", http.StatusInternalServerError)
log.Errorf("Marshal error: %v", err)
return
}
w.WriteHeader(http.StatusOK)
_, err = w.Write(rdata)
if err != nil {
log.Errorf("Write error: %v", err)
}
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Treat it as a server code defect: inspect recent changes to types.GetURLResponse for chan/func/self-referential fields
- Add a unit test asserting json.Marshal(GetURLResponse{}) succeeds so the regression is caught before deploy
- Client side: report the 500; no request change will avoid it
Defensive patterns
Strategy: try-catch
Try / catch
On 500 'failed to marshal response', retry the GET once (transient code path is theoretically impossible), then report it upstream as a server regression in types.GetURLResponse.
Prevention
- Keep a unit test asserting json.Marshal(types.GetURLResponse{}) succeeds
- Never add chan/func or self-referential fields to response DTOs
When it happens
Trigger: Only reachable if GetURLResponse is extended with a field json.Marshal rejects or a self-referential type; with the current two-string struct the branch is dead code.
Common situations: Practically never in production; would surface immediately after a change to upload-server/types/upload.go, typically in CI or a canary deployment.
Related errors
- invalid duration
- failed to list profiles: %w
- failed to read profile config: %w
- parse service params %s: %w
- failed to parse signature: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/46271eb93bb32c0b.
Report an issue: GitHub.