{"record":{"id":"afbb1ef7587820a4","repo":"cayleygraph/cayley","slug":"regexp-from-non-string-value-t","errorCode":null,"errorMessage":"regexp from non-string value: %T","messagePattern":"regexp from non-string value: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"query/gizmo/environ.go","lineNumber":231,"sourceCode":"\t\tif !allowRefs {\n\t\t\treturn throwErr(vm, errRegexpOnIRI)\n\t\t}\n\tdefault:\n\t\treturn throwErr(vm, fmt.Errorf(\"regexp: unsupported type: %T\", v))\n\t}\n\tvar (\n\t\ts    string\n\t\trefs bool\n\t)\n\tswitch v := v.(type) {\n\tcase quad.String:\n\t\ts = string(v)\n\tcase quad.IRI:\n\t\ts, refs = string(v), true\n\tcase quad.BNode:\n\t\ts, refs = string(v), true\n\tdefault:\n\t\treturn throwErr(vm, fmt.Errorf(\"regexp from non-string value: %T\", v))\n\t}\n\tre, err := regexp.Compile(string(s))\n\tif err != nil {\n\t\treturn throwErr(vm, err)\n\t}\n\treturn vm.ToValue(valFilter{f: shape.Regexp{Re: re, Refs: refs}})\n}\n\ntype valFilter struct {\n\tf shape.ValueFilter\n}\n\nvar defaultEnv = map[string]func(vm *goja.Runtime, call goja.FunctionCall) goja.Value{\n\t\"iri\":   oneStringType(func(s string) quad.Value { return quad.IRI(s) }),\n\t\"bnode\": oneStringType(func(s string) quad.Value { return quad.BNode(s) }),\n\t\"raw\":   oneStringType(func(s string) quad.Value { return quad.Raw(s) }),\n\t\"str\":   oneStringType(func(s string) quad.Value { return quad.String(s) }),\n","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/query/gizmo/environ.go#L213-L249","documentation":"After cmpRegexp validates that the value is a string-like quad type, a second switch converts it to the pattern string. This default branch is a defensive invariant check: since the first switch already rejected non-string-like types, reaching it means the value type still isn't quad.String, quad.IRI, or quad.BNode when compiling the regexp. The error names the offending type.","triggerScenarios":"Practically unreachable through normal cmpRegexp input; could only occur if toQuadValue or the preceding switch logic changes (e.g. a new quad.Value type added and only one of the two switches updated), or via an allowRefs conversion path producing an unexpected type.","commonSituations":"Developers extending environ.go with new quad value types but updating only one type switch; custom quad.Value implementations reaching the regexp filter path.","solutions":["Update both type switches in cmpRegexp to handle the new quad.Value type consistently","Ensure any value reaching regexp compilation is quad.String, quad.IRI, or quad.BNode","Check for recent changes to toQuadValue or quad package types that added variants"],"exampleFix":"// before\ndefault:\n    return throwErr(vm, fmt.Errorf(\"regexp from non-string value: %T\", v))\n// after\ncase quad.TypedString:\n    s, refs = string(v), false\ndefault:\n    return throwErr(vm, fmt.Errorf(\"regexp from non-string value: %T\", v))","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  g.V().Has(\"name\", regexp(v))\n} catch (e) {\n  log(String(e)); // includes \"regexp from non-string value\" — report as a bug if hit\n}","preventionTips":["Keep both type switches in cmpRegexp in sync when adding quad types","Add unit tests covering every quad.Value variant through cmpRegexp","Review toQuadValue changes for new type variants"],"tags":["query","regexp","invariant","internal"],"backgroundTag":"internal-invariant-violation","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"}