{"record":{"id":"13923b45a4d0790c","repo":"cayleygraph/cayley","slug":"http-request-needed","errorCode":null,"errorMessage":"HTTP Request needed","messagePattern":"HTTP Request needed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/gaedatastore/quadstore.go","lineNumber":157,"sourceCode":"\t}\n\tif _, ok := err.(*datastore.ErrFieldMismatch); ok {\n\t\treturn true, nil\n\t}\n\tif err != nil {\n\t\tclog.Warningf(\"Error occurred when getting quad/node %s %v\", k, err)\n\t\treturn false, err\n\t}\n\t// a deleted node should not be returned as found.\n\tif len(q.Deleted) >= len(q.Added) {\n\t\treturn false, nil\n\t}\n\treturn true, nil\n}\n\nfunc getContext(opts graph.Options) (context.Context, error) {\n\treq := opts[\"HTTPRequest\"].(*http.Request)\n\tif req == nil {\n\t\terr := errors.New(\"HTTP Request needed\")\n\t\tclog.Errorf(\"%v\", err)\n\t\treturn nil, err\n\t}\n\treturn appengine.NewContext(req), nil\n}\n\nfunc (qs *QuadStore) ForRequest(r *http.Request) (graph.QuadStore, error) {\n\treturn &QuadStore{context: appengine.NewContext(r)}, nil\n}\n\nfunc (qs *QuadStore) NewQuadWriter() (quad.WriteCloser, error) {\n\treturn &quadWriter{qs: qs}, nil\n}\n\ntype quadWriter struct {\n\tqs     *QuadStore\n\tdeltas []graph.Delta\n}","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/gaedatastore/quadstore.go#L139-L175","documentation":"getContext in the Google App Engine datastore QuadStore requires an incoming *http.Request to derive an App Engine context (appengine.NewContext). If the graph.Options map does not contain a non-nil \"HTTPRequest\" entry, initialization fails and the quadstore cannot talk to the datastore. This is a mandatory option for this backend.","triggerScenarios":"Calling gaedatastore.New (via graph.NewQuadStore / cayley config) without passing opts[\"HTTPRequest\"], or passing something other than *http.Request (e.g. nil or wrong type).","commonSituations":"Running Cayley inside Google App Engine but opening the store outside an HTTP request handler; forgetting to forward the handler's r *http.Request into graph.Options; using an appengine backend in a non-GAE environment.","solutions":["Obtain the store from within an HTTP handler and pass the request: opts[\"HTTPRequest\"] = r in the graph.Options map.","If not on App Engine, switch to a different quadstore backend (e.g. bolt, memory) via config instead of gaedatastore.","Verify the option value is exactly *http.Request, not a wrapped or nil value.","Check the appengine SDK import path matches your runtime (google.golang.org/appengine vs legacy appengine)."],"exampleFix":"// before\nqs, err := graph.NewQuadStore(\"gaedatastore\", \"\", graph.Options{})\n// after (inside an http handler)\nqs, err := graph.NewQuadStore(\"gaedatastore\", \"\", graph.Options{\"HTTPRequest\": r})","handlingStrategy":"validation","validationCode":"if req, ok := opts[\"HTTPRequest\"].(*http.Request); !ok || req == nil {\n    return errors.New(\"gaedatastore requires opts[\\\"HTTPRequest\\\"] to be *http.Request\")\n}","typeGuard":"func hasHTTPRequest(opts graph.Options) bool {\n    r, ok := opts[\"HTTPRequest\"].(*http.Request)\n    return ok && r != nil\n}","tryCatchPattern":"qs, err := graph.NewQuadStore(\"gaedatastore\", \"\", opts)\nif err != nil {\n    return fmt.Errorf(\"gae store init failed: %w\", err)\n}","preventionTips":["Always open the gaedatastore inside an HTTP handler and pass r into graph.Options.","Never ignore the error from NewQuadStore/New before using the store.","Use a different backend if not running on App Engine.","Assert the option type at startup with a small helper."],"tags":["appengine","initialization","http-request","configuration"],"backgroundTag":"missing-required-option","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}