cayleygraph/cayley · error

format is not supported for reading nodes

Error message

format is not supported for reading nodes

What it means

The v2 HTTP node-delete endpoint reads a single node value from the request body and needs a format with UnmarshalValue. If the Content-Type does not map to a format capable of unmarshaling node values, the endpoint returns 400 with this message.

Source

Thrown at server/http/api_v2.go:314

	if err != nil {
		jsonResponse(w, http.StatusInternalServerError, err)
		return
	}
	w.Header().Set(hdrContentType, contentTypeJSON)
	fmt.Fprintf(w, `{"result": "Successfully deleted %d quads.", "count": %d}`+"\n", n, n)
}

// ServeNodeDelete deletes all data associated with a node (an entity).
// Responds with how many quads were deleted.
func (api *APIv2) ServeNodeDelete(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	if api.ro {
		jsonResponse(w, http.StatusForbidden, errors.New("database is read-only"))
		return
	}
	format := getFormat(r, "", hdrContentType)
	if format == nil || format.UnmarshalValue == nil {
		jsonResponse(w, http.StatusBadRequest, fmt.Errorf("format is not supported for reading nodes"))
		return
	}
	const limit = 128*1024 + 1
	rd := io.LimitReader(r.Body, limit)
	data, err := ioutil.ReadAll(rd)
	if err != nil {
		jsonResponse(w, http.StatusBadRequest, err)
		return
	} else if len(data) == limit {
		jsonResponse(w, http.StatusBadRequest, fmt.Errorf("request data is too large"))
		return
	}
	v, err := format.UnmarshalValue(data)
	if err != nil {
		jsonResponse(w, http.StatusBadRequest, err)
		return
	} else if v == nil {
		jsonResponse(w, http.StatusBadRequest, fmt.Errorf("cannot remove nil value"))

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Set Content-Type to a node-capable format (e.g. application/json) on the node DELETE request
  2. Verify the server registered the format with UnmarshalValue support
  3. Use /api/v2/data with a quad Reader format instead if deleting a batch of quads

Example fix

// before
curl -X DELETE -H 'Content-Type: application/n-quads' --data '"n1"' .../node
// after
curl -X DELETE -H 'Content-Type: application/json' --data '"n1"' .../node
Defensive patterns

Strategy: validation

Validate before calling

req.Header.Set("Content-Type", "application/json") // node endpoint needs a value format

Try / catch

resp, err := client.Do(req)
if err != nil { return err }
if resp.StatusCode == http.StatusBadRequest {
    b, _ := io.ReadAll(resp.Body)
    if strings.Contains(string(b), "reading nodes") {
        return fmt.Errorf("use application/json for node delete: %s", b)
    }
    return fmt.Errorf("node delete rejected: %s", b)
}

Prevention

When it happens

Trigger: Sending a DELETE to /api/v2/node with a Content-Type whose format lacks UnmarshalValue (e.g. quad-oriented formats like nquads instead of a node format like JSON), or with an unknown/missing Content-Type.

Common situations: Clients reusing the data endpoint's Content-Type for the node endpoint; servers without JSON format registered; header typos or missing charset handling.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/d5de0e172596f6ed. Report an issue: GitHub.