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

  1. Validate the body client-side before sending: pipe through `jq .`, JSON.parse, or Go json.Valid
  2. Compare against a known-good request with curl --data-binary @request.json
  3. Check for proxy/gateway body truncation (Content-Length vs actual bytes) if the same client works locally
  4. 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

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

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/b9efcb6ef83780c9. Report an issue: GitHub.