{"record":{"id":"5bdb8a89af6bf241","repo":"cayleygraph/cayley","slug":"gae-quad-token-not-valid","errorCode":null,"errorMessage":"gae quad: token not valid","messagePattern":"gae quad: token not valid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/gaedatastore/quadstore.go","lineNumber":489,"sourceCode":"\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 != \"\" {\n\t\tlabel = q.Label\n\t}\n\treturn quad.Make(\n\t\tq.Subject,\n\t\tq.Predicate,\n\t\tq.Object,","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/gaedatastore/quadstore.go#L471-L507","documentation":"Quad requires a *Token with Kind quadKind to construct the datastore key for the QuadEntry. Any other ref type or token kind yields this error, and the quad cannot be fetched.","triggerScenarios":"Passing a nodeKind Token, a raw hash ref, or a PreFetchedValue into Quad; mixing node and quad tokens when caching references.","commonSituations":"Confusing results of NameFor (node tokens) with QuadIterator tokens (quad tokens); refactoring across the old Value/Key API; storing token strings and re-parsing them incorrectly.","solutions":["Ensure the ref comes from quad iteration / quadsOf paths, i.e. has Kind quadKind.","Type-check before calling: t, ok := val.(*Token); ok && t.Kind == quadKind.","Use NameOf for nodeKind tokens instead.","Fix serialization that flattens tokens and loses Kind information."],"exampleFix":"// before\nq, err := qs.Quad(nodeToken)\n// after\nif t, ok := ref.(*Token); ok && t.Kind == quadKind {\n    q, err = qs.Quad(ref)\n}","handlingStrategy":"type-guard","validationCode":"if t, ok := ref.(*Token); !ok || t.Kind != quadKind {\n    return errors.New(\"Quad requires a quadKind Token\")\n}","typeGuard":"func isQuadToken(ref graph.Ref) bool {\n    t, ok := ref.(*Token)\n    return ok && t.Kind == quadKind\n}","tryCatchPattern":"q, err := qs.Quad(ref)\nif err != nil {\n    if strings.Contains(err.Error(), \"token not valid\") {\n        // wrong token kind; use NameOf for node tokens\n    }\n    return err\n}","preventionTips":["Only pass tokens from quad iteration to Quad().","Keep token Kind assertions at API boundaries.","Avoid re-parsing serialized tokens that may lose Kind."],"tags":["datastore","token","invalid-argument","type-mismatch"],"backgroundTag":"invalid-argument-value","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"}