{"record":{"id":"d950ea0560def8a4","repo":"cayleygraph/cayley","slug":"request-is-too-large","errorCode":null,"errorMessage":"request is too large","messagePattern":"request is too large","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/http/write.go","lineNumber":67,"sourceCode":"\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 {\n\t\tjsonResponse(w, 400, \"Database is read-only.\")\n\t\treturn\n\t}\n\t// TODO: streaming reader\n\tbodyBytes, err := readLimit(r.Body)\n\tif err != nil {\n\t\tjsonResponse(w, 400, err)\n\t\treturn\n\t}\n\tquads, err := ParseJSONToQuadList(bodyBytes)\n\tif err != nil {\n\t\tjsonResponse(w, 400, err)","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/internal/http/write.go#L49-L85","documentation":"readLimit caps any v1 write/delete request body at maxQuerySize (1 MiB). It reads via io.LimitReader; if the body fills (or exceeds) the limit, ioutil.ReadAll reports an error and lr.N <= 0 signals the reader was exhausted, so the function replaces it with \"request is too large\". The library enforces this to prevent unbounded memory use from large bulk writes.","triggerScenarios":"POSTing to /api/v1/write or /api/v1/delete with a JSON body larger than 1024*1024 bytes (1 MB). Any payload whose size reaches the LimitReader cap triggers this regardless of content validity.","commonSituations":"Bulk-loading a large N-Quads/JSON set in a single request instead of chunking; migrating data from another store via one huge write call; scripts that concatenate many quads into one POST; proxy/gateway timeouts prompting clients to batch aggressively.","solutions":["Split the payload into chunks smaller than 1 MB and issue multiple /api/v1/write (or /delete) requests.","Use the dedicated bulk loader tool (cayley load) or the load endpoint for large datasets instead of the HTTP write API.","Compress/deduplicate the data before sending to get under the cap.","If you truly need bigger requests, fork/rebuild with a larger maxQuerySize (internal/http/write.go)."],"exampleFix":"// before\nbody := buildAllQuadsJSON() // 5 MB\nhttp.Post(url, \"application/json\", strings.NewReader(body))\n// after\nfor _, chunk := range chunkBytes(buildAllQuadsJSON(), 900*1024) {\n    http.Post(url, \"application/json\", bytes.NewReader(chunk))\n}","handlingStrategy":"validation","validationCode":"const maxQuerySize = 1024 * 1024\nif len(payload) >= maxQuerySize {\n    return errors.New(\"payload must be chunked under 1 MiB for /api/v1/write\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Post(writeURL, \"application/json\", bytes.NewReader(chunk))\nif err != nil { return err }\nif resp.StatusCode == http.StatusBadRequest {\n    b, _ := io.ReadAll(resp.Body)\n    if strings.Contains(string(b), \"request is too large\") {\n        return chunkAndRetry(chunk)\n    }\n}","preventionTips":["Chunk all write/delete payloads well below 1 MiB (e.g. 900 KB) before POSTing.","Use the bulk loader (cayley load) for large imports instead of the HTTP write API.","Add a size assertion in your data-pipeline tests for generated request bodies."],"tags":["http","request-size","limit","write-api"],"backgroundTag":"payload-too-large","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"}