cayleygraph/cayley · error

Error updating log, context is nil, graph not correctly init

Error message

Error updating log, context is nil, graph not correctly initialised

What it means

updateLog writes a LogEntry batch to the datastore for each applied delta; it needs the App Engine context to make the datastore call. A nil context means the store is not correctly initialized, so the log update cannot proceed.

Source

Thrown at graph/gaedatastore/quadstore.go:404

		err := datastore.Get(c, key, foundMetadata)
		if err != nil && err != datastore.ErrNoSuchEntity {
			clog.Errorf("Error: %v", err)
			return err
		}
		foundMetadata.QuadCount += quadsAdded
		foundMetadata.NodeCount += nodesAdded
		_, err = datastore.Put(c, key, foundMetadata)
		if err != nil {
			clog.Errorf("Error: %v", err)
		}
		return err
	}, nil)
	return err
}

func (qs *QuadStore) updateLog(in []graph.Delta) ([]int64, error) {
	if qs.context == nil {
		err := errors.New("Error updating log, context is nil, graph not correctly initialised")
		return nil, err
	}
	if len(in) == 0 {
		return nil, errors.New("Nothing to log")
	}
	logEntries := make([]LogEntry, 0, len(in))
	logKeys := make([]*datastore.Key, 0, len(in))
	for _, d := range in {
		var action string
		if d.Action == graph.Add {
			action = "Add"
		} else {
			action = "Delete"
		}

		entry := LogEntry{
			Action:    action,
			Key:       qs.createKeyForQuad(d.Quad).String(),

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Ensure the QuadStore is fully initialized (qs.context != nil) before writing; check New's error return.
  2. Synchronize store initialization and writes; do not re-initialize a store mid-request.
  3. Re-create the store inside the current request handler if the context is stale.
  4. Add a nil-context guard before calling write APIs.

Example fix

// before
ids, err := qs.updateLog(deltas) // may fail with nil context
// after
if qs.context == nil { return errors.New("gae context missing") }
ids, err := qs.updateLog(deltas)
Defensive patterns

Strategy: validation

Validate before calling

if qs.context == nil || len(deltas) == 0 {
    return errors.New("cannot update log: missing context or empty deltas")
}

Type guard

func canLog(qs *QuadStore, ds []graph.Delta) bool { return qs.context != nil && len(ds) > 0 }

Try / catch

ids, err := qs.updateLog(deltas)
if err != nil {
    if strings.Contains(err.Error(), "context is nil") {
        // re-initialize store with request context
    }
    return err
}

Prevention

When it happens

Trigger: updateLog called (only from ApplyDeltas) after qs.context was nil — i.e. the store was created without a valid HTTPRequest-derived App Engine context; ApplyDeltas' nil check passed only if context was set, so this usually indicates a race or re-init clearing context.

Common situations: Store re-initialized or partially constructed concurrently while writes are in flight; earlier init error ignored; using the same QuadStore across different App Engine request scopes.

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