cayleygraph/cayley · error

context is nil, graph is not correctly initialized

Error message

context is nil, graph is not correctly initialized

What it means

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.

Source

Thrown at graph/gaedatastore/quadstore.go:483

	if t, ok := val.(*Token); ok && t.Kind == nodeKind {
		key = qs.createKeyFromToken(t)
	} else {
		return nil, errors.New("token not valid")
	}

	// TODO (panamafrancis) implement a cache

	node := new(NodeEntry)
	err := datastore.Get(qs.context, key, node)
	if err != nil {
		return nil, err
	}
	return quad.Raw(node.Name), nil
}

func (qs *QuadStore) Quad(val graph.Ref) (quad.Quad, error) {
	if qs.context == nil {
		return quad.Quad{}, errors.New("context is nil, graph is not correctly initialized")
	}
	var key *datastore.Key
	if t, ok := val.(*Token); ok && t.Kind == quadKind {
		key = qs.createKeyFromToken(t)
	} else {
		return quad.Quad{}, errors.New("gae quad: token not valid")
	}

	q := new(QuadEntry)
	err := datastore.Get(qs.context, key, q)
	if err != nil {
		// Red herring error : ErrFieldMismatch can happen when a quad exists but a field is empty
		if _, ok := err.(*datastore.ErrFieldMismatch); !ok {
			return quad.Quad{}, err
		}
	}
	var label interface{}
	if q.Label != "" {

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Create the store inside a request handler with opts["HTTPRequest"] set.
  2. Handle the error from store creation before issuing reads.
  3. For background work, use a context-compatible appengine backend pattern (e.g. context.Background via appengine.BackgroundContext if available) or a different quadstore.
  4. Verify deployment target actually supports App Engine contexts.

Example fix

// before
q, err := qs.Quad(ref) // panics-free but errors: context nil
// after
if qs.context == nil { return quad.Quad{}, errors.New("gae store not initialized") }
q, err = qs.Quad(ref)
Defensive patterns

Strategy: validation

Validate before calling

if qs.context == nil {
    return errors.New("gaedatastore not initialized; Quad unavailable")
}

Type guard

func quadReadable(qs *QuadStore) bool { return qs.context != nil }

Try / catch

q, err := qs.Quad(ref)
if err != nil {
    if strings.Contains(err.Error(), "not correctly initialized") {
        // re-init with request context and retry once
    }
    return err
}

Prevention

When it happens

Trigger: Calling Quad (directly or via allQuads, IteratedQuadsNext, ReadQuad, serveRawQuads, iterateObject) on a QuadStore initialized without a valid HTTPRequest-derived context.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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