{"record":{"id":"037a68a6750d7a57","repo":"cayleygraph/cayley","slug":"context-is-nil-graph-is-not-correctly-initialized","errorCode":null,"errorMessage":"context is nil, graph is not correctly initialized","messagePattern":"context is nil, graph is not correctly initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/gaedatastore/quadstore.go","lineNumber":483,"sourceCode":"\tif t, ok := val.(*Token); ok && t.Kind == nodeKind {\n\t\tkey = qs.createKeyFromToken(t)\n\t} else {\n\t\treturn nil, errors.New(\"token not valid\")\n\t}\n\n\t// TODO (panamafrancis) implement a cache\n\n\tnode := new(NodeEntry)\n\terr := datastore.Get(qs.context, key, node)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn quad.Raw(node.Name), nil\n}\n\nfunc (qs *QuadStore) Quad(val graph.Ref) (quad.Quad, error) {\n\tif qs.context == nil {\n\t\treturn quad.Quad{}, errors.New(\"context is nil, graph is not correctly initialized\")\n\t}\n\tvar key *datastore.Key\n\tif t, ok := val.(*Token); ok && t.Kind == quadKind {\n\t\tkey = qs.createKeyFromToken(t)\n\t} else {\n\t\treturn quad.Quad{}, errors.New(\"gae quad: token not valid\")\n\t}\n\n\tq := new(QuadEntry)\n\terr := datastore.Get(qs.context, key, q)\n\tif err != nil {\n\t\t// Red herring error : ErrFieldMismatch can happen when a quad exists but a field is empty\n\t\tif _, ok := err.(*datastore.ErrFieldMismatch); !ok {\n\t\t\treturn quad.Quad{}, err\n\t\t}\n\t}\n\tvar label interface{}\n\tif q.Label != \"\" {","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/gaedatastore/quadstore.go#L465-L501","documentation":"Quad reconstructs a full quad from a stored QuadEntry via a datastore Get, which requires the App Engine context. Nil context means the store is not initialized and quads cannot be read.","triggerScenarios":"Calling Quad (directly or via allQuads, IteratedQuadsNext, ReadQuad, serveRawQuads, iterateObject) on a QuadStore initialized without a valid HTTPRequest-derived context.","commonSituations":"Querying the store from a background task or cold-start path without a request; ignoring init errors; running the GAE backend on Compute Engine or locally where appengine.NewContext cannot work.","solutions":["Create the store inside a request handler with opts[\"HTTPRequest\"] set.","Handle the error from store creation before issuing reads.","For background work, use a context-compatible appengine backend pattern (e.g. context.Background via appengine.BackgroundContext if available) or a different quadstore.","Verify deployment target actually supports App Engine contexts."],"exampleFix":"// before\nq, err := qs.Quad(ref) // panics-free but errors: context nil\n// after\nif qs.context == nil { return quad.Quad{}, errors.New(\"gae store not initialized\") }\nq, err = qs.Quad(ref)","handlingStrategy":"validation","validationCode":"if qs.context == nil {\n    return errors.New(\"gaedatastore not initialized; Quad unavailable\")\n}","typeGuard":"func quadReadable(qs *QuadStore) bool { return qs.context != nil }","tryCatchPattern":"q, err := qs.Quad(ref)\nif err != nil {\n    if strings.Contains(err.Error(), \"not correctly initialized\") {\n        // re-init with request context and retry once\n    }\n    return err\n}","preventionTips":["Open the store per-request with opts[\"HTTPRequest\"] = r.","Handle init errors before querying.","Do not share a GAE store across request scopes after init failure.","Use non-GAE backends for background/cron work."],"tags":["appengine","read","initialization","state"],"backgroundTag":"invalid-state-transition","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"}