goharbor/harbor · error
invalid json request
Error message
invalid json request
What it means
DecodeJSONReq is the shared decoder for every JSON request body handled by Harbor core API handlers. It runs json.Unmarshal on the copied body (up to 1<<35 bytes); on failure it logs the underlying json error plus the body prefix and returns a sanitized 'invalid json request' error so raw parse details never leak to the client.
Source
Thrown at src/common/api/base.go:87
func (b *BaseAPI) Render() error {
return nil
}
// RenderError provides shortcut to render http error
func (b *BaseAPI) RenderError(code int, text string) {
lib_http.SendError(b.Ctx.ResponseWriter, &commonhttp.Error{
Code: code,
Message: text,
})
}
// DecodeJSONReq decodes a json request
func (b *BaseAPI) DecodeJSONReq(v any) error {
err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<35), v)
if err != nil {
log.Errorf("Error while decoding the json request, error: %v, %v",
err, string(b.Ctx.Input.CopyBody(1 << 35)[:]))
return errors.New("invalid json request")
}
return nil
}
// Validate validates v if it implements interface validation.ValidFormer
func (b *BaseAPI) Validate(v any) (bool, error) {
validator := validation.Validation{}
isValid, err := validator.Valid(v)
if err != nil {
log.Errorf("failed to validate: %v", err)
return false, err
}
if !isValid {
var message strings.Builder
for _, e := range validator.Errors {
message.WriteString(fmt.Sprintf("%s %s \n", e.Field, e.Message))
}View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Validate the body client-side before sending: pipe through `jq .`, JSON.parse, or Go json.Valid
- Compare against a known-good request with curl --data-binary @request.json
- Check for proxy/gateway body truncation (Content-Length vs actual bytes) if the same client works locally
- Inspect harbor-core logs — the error line contains the exact json.Unmarshal failure and a body prefix pinpointing the offending offset
Example fix
# before (shell quoting mangles the JSON)
curl -X POST -H 'Content-Type: application/json' -d "{name: \"proj\"}" https://harbor/api/v2.0/projects
# after
curl -X POST -H 'Content-Type: application/json' -d '{"name":"proj"}' https://harbor/api/v2.0/projects Defensive patterns
Strategy: validation
Validate before calling
// client-side, before sending
if !json.Valid(body) {
return fmt.Errorf("refusing to send invalid JSON: %s", body)
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json") Try / catch
if err := api.DecodeJSONReq(v); err != nil {
if strings.Contains(err.Error(), "invalid json request") {
// body-level JSON problem: log and reject the request, do not retry unchanged
}
} Prevention
- Build request bodies by marshaling a typed struct instead of string concatenation
- Pipe manual curl payloads through jq . first
- Check harbor-core logs for the embedded json.Unmarshal offset when debugging
When it happens
Trigger: Any POST/PUT to a Harbor core API endpoint whose body fails json.Unmarshal for the target struct: syntax errors, trailing commas, single-quoted strings, wrong field types, truncated bodies, extra characters after the top-level JSON value, or a body that is not JSON at all.
Common situations: Hand-written curl with shell-quoting mistakes, clients sending form-encoded data while claiming Content-Type: application/json, proxies or CDNs truncating bodies, UTF-8 BOM prefixes, mismatched Content-Length.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Internal dir for tls {} not exist
- Trace enabled but no trace exporter set
- 10013
- File {} not exist
- Port number in metrics is not valid
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/b9efcb6ef83780c9.
Report an issue: GitHub.