siyuan-note/siyuan · error

Parses request [ ] failed

Error message

Parses request [%s] failed: %s

What it means

Generic request parse failure for all endpoints that decode their body into a field map via blockRequestFields. The message embeds the API path (%s) and the underlying json error, e.g. 'Parses request [/api/block/checkBlockRef] failed: invalid character ...'. It means the body was readable but is not valid JSON or not a JSON object.

Solutions

  1. Validate the body with a JSON parser before sending and fix syntax errors.
  2. Use Content-Type: application/json and a real serializer instead of string concatenation.
  3. Read the embedded json error after 'failed:' — it pinpoints the exact character/offset.
  4. Compare against a known-good request example from the API docs.

Example fix

// before
{"id": "x",} // trailing comma
// after
{"id": "x"}
Defensive patterns

Strategy: validation

Validate before calling

try { JSON.parse(bodyString); } catch (e) { throw new Error("request body is not valid JSON: " + e.message); }

Try / catch

try {
  await post(path, body);
} catch (e) {
  if (String(e.message).startsWith("Parses request")) {
    // embedded json error after 'failed:' names the bad character/offset
    console.error("Malformed JSON for", path, bodyString);
  } else { throw e; }
}

Prevention

When it happens

Trigger: POSTing malformed JSON (trailing commas, single quotes, unquoted keys, concatenated objects) to any blockRequestFields-backed endpoint such as /api/block/checkBlockRef, heading-level transactions, bazaar, or AV requests.

Common situations: Hand-built payload strings with syntax errors, templates/interpolation injecting raw values, text/plain or form-encoded bodies sent to a JSON endpoint, or a proxy rewriting the body.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/f80535c823dae2aa. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/block_remaining.go:61

// 特殊解码仅保留这些入口的条件参数和结构体绑定语义,响应仍受各自的契约约束。
func init() {
	CheckBlockRef.decodeRequest = decodeCheckBlockRef
	GetHeadingLevelTransaction.decodeRequest = decodeHeadingLevel
	GetDocHeadingLevelTransaction.decodeRequest = func(reader io.Reader) (request DocHeadingLevelRequest, err error) {
		if json.NewDecoder(reader).Decode(&request) != nil {
			err = errors.New("invalid heading conversion parameters")
		}
		return
	}
}

func blockRequestFields(reader io.Reader, path string) (fields map[string]json.RawMessage, err error) {
	err = json.NewDecoder(reader).Decode(&fields)
	if err != nil {
		if errors.Is(err, io.EOF) {
			err = errors.New("the request body is empty or truncated (EOF)")
		}
		err = fmt.Errorf("Parses request [%s] failed: %s", path, err)
	}
	return
}

func decodeCheckBlockRef(reader io.Reader) (request CheckBlockRefRequest, err error) {
	fields, err := blockRequestFields(reader, "/api/block/checkBlockRef")
	if err != nil {
		return request, err
	}
	if raw, present := fields["scope"]; present {
		if bytes.Equal(raw, []byte("null")) || json.Unmarshal(raw, &request.Scope) != nil {
			return request, errors.New("Field [scope] should be of type [String]")
		}
	}
	if strings.TrimSpace(request.Scope) == "" {
		request.Scope = "blocks"
	}
	readArray := func(key string, required, nonempty bool) ([]string, error) {

View on GitHub (pinned to 9f775e8a12)