cayleygraph/cayley · error

context is nil, graph is not initialized

Error message

context is nil, graph is not initialized

What it means

NameOf resolves a node reference to its quad.Value via a datastore lookup, which requires the App Engine request context. A nil context means the store was not initialized, so node names cannot be fetched.

Source

Thrown at graph/gaedatastore/quadstore.go:460

	return qs.newIterator(quadKind, dir, v)
}

func (qs *QuadStore) NodesAllIterator() iterator.Shape {
	return qs.newAllIterator(nodeKind)
}

func (qs *QuadStore) QuadsAllIterator() iterator.Shape {
	return qs.newAllIterator(quadKind)
}

func (qs *QuadStore) ValueOf(s quad.Value) (graph.Ref, error) {
	id := hashOf(s)
	return &Token{Kind: nodeKind, Hash: id}, nil
}

func (qs *QuadStore) NameOf(val graph.Ref) (quad.Value, error) {
	if qs.context == nil {
		return nil, errors.New("context is nil, graph is not initialized")
	} else if v, ok := val.(refs.PreFetchedValue); ok {
		return v.NameOf(), nil
	}
	var key *datastore.Key
	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

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Initialize the store within a request handler passing opts["HTTPRequest"] = r.
  2. Check and handle the error from store creation before any reads.
  3. For PreFetchedValue refs the lookup is bypassed — consider pre-fetching values to reduce datastore dependency.
  4. Switch backends if you are not actually running on App Engine.

Example fix

// before
val, err := qs.NameOf(ref)
// after
if qs.context == nil { return nil, errors.New("store missing gae context") }
val, err := qs.NameOf(ref)
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

val, err := qs.NameOf(ref)
if err != nil {
    if strings.Contains(err.Error(), "not initialized") {
        // re-create store with current request
    }
    return err
}

Prevention

When it happens

Trigger: Calling NameOf (directly or via String, Contains, IteratedStrings/Values, iterator Next/Contains) on a QuadStore whose context is nil because getContext failed at init.

Common situations: Store opened at module init outside a request; ignoring New's error then querying; using the GAE backend outside Google App Engine entirely.

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/d1409a3d12c1d1f6. Report an issue: GitHub.