{"record":{"id":"ff3cb503d3e7f0aa","repo":"cayleygraph/cayley","slug":"invalid-quad-at-index-d-s","errorCode":null,"errorMessage":"invalid quad at index %d. %s","messagePattern":"invalid quad at index (.+?)\\. (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/http/write.go","lineNumber":55,"sourceCode":"\t\tSubject   string `json:\"subject\"`\n\t\tPredicate string `json:\"predicate\"`\n\t\tObject    string `json:\"object\"`\n\t\tLabel     string `json:\"label\"`\n\t}\n\terr := json.Unmarshal(jsonBody, &quads)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tout = make([]quad.Quad, 0, len(quads))\n\tfor i, jq := range quads {\n\t\tq := quad.Quad{\n\t\t\tSubject:   quad.StringToValue(jq.Subject),\n\t\t\tPredicate: quad.StringToValue(jq.Predicate),\n\t\t\tObject:    quad.StringToValue(jq.Object),\n\t\t\tLabel:     quad.StringToValue(jq.Label),\n\t\t}\n\t\tif !q.IsValid() {\n\t\t\treturn nil, fmt.Errorf(\"invalid quad at index %d. %s\", i, q)\n\t\t}\n\t\tout = append(out, q)\n\t}\n\treturn out, nil\n}\n\nconst maxQuerySize = 1024 * 1024 // 1 MB\nfunc readLimit(r io.Reader) ([]byte, error) {\n\tlr := io.LimitReader(r, maxQuerySize).(*io.LimitedReader)\n\tdata, err := ioutil.ReadAll(lr)\n\tif err != nil && lr.N <= 0 {\n\t\terr = errors.New(\"request is too large\")\n\t}\n\treturn data, err\n}\n\nfunc (api *API) ServeV1Write(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\tif api.config.ReadOnly {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/internal/http/write.go#L37-L73","documentation":"The HTTP v1 write/delete endpoints parse JSON objects into quad.Quad values. Each parsed quad is validated with q.IsValid(); if subject/predicate/object (or label) combination is invalid — e.g. empty predicate, nil values, or mismatched BNode names — the request is rejected with the index and the invalid quad in the message.","triggerScenarios":"POSTing to /api/v1/write or /delete a JSON body where a quad entry has missing/empty fields, wrong types (numbers instead of strings), or invalid values that quad.StringToValue cannot make valid.","commonSituations":"Hand-written or generated JSON payloads omitting the \"object\" field; using null for subject/predicate; BNode labels reused incorrectly; bulk loads with a malformed line mid-array.","solutions":["Check the quad at the reported index in your JSON array and fix its fields","Ensure subject, predicate, and object are non-empty and provided as strings","Validate quads client-side with quad.StringToValue + IsValid before sending","Log the full request body to find the offending entry"],"exampleFix":"// before\n{\"subject\": \"\", \"predicate\": \"likes\", \"object\": \"alice\"} // invalid: empty subject\n// after\n{\"subject\": \"bob\", \"predicate\": \"likes\", \"object\": \"alice\"}","handlingStrategy":"validation","validationCode":"for i, jq := range payload.Quads {\n    q := quad.Quad{\n        Subject: quad.StringToValue(jq.Subject),\n        Predicate: quad.StringToValue(jq.Predicate),\n        Object: quad.StringToValue(jq.Object),\n        Label: quad.StringToValue(jq.Label),\n    }\n    if !q.IsValid() { return fmt.Errorf(\"quad %d invalid\", i) }\n}","typeGuard":null,"tryCatchPattern":"resp, err := http.Post(url, \"application/json\", body)\nif err == nil && resp.StatusCode == 400 {\n    var e map[string]interface{}\n    json.NewDecoder(resp.Body).Decode(&e)\n    // inspect error message for the failing index\n}","preventionTips":["Validate quads client-side with IsValid before POSTing","Reject null/empty fields in your JSON generation code","Log full payloads when a write fails"],"tags":["http","json","validation","quads"],"backgroundTag":"schema-validation-failed","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}