facebook/relay · error
Node.search exists
Error message
Node.search exists
What it means
This is a Rust panic from `.expect("Node.search exists")` in the test `sorts_arguments_interfaces_and_directives_alphabetically` (compiler/crates/schema-set/src/build_in_memory_schema.rs:835). It fires when `schema.named_field(node_type, "search".intern())` returns None, meaning the in-memory schema built from the SDL does not expose a field named `search` on the `Node` object. The library throws it because the test treats a missing field as unrecoverable: without the field there is nothing to sort arguments/directives for. In production code the same lookup API returns an Option/Result that callers must handle.
Source
Thrown at compiler/crates/schema-set/src/build_in_memory_schema.rs:835
let node = schema.object(node_type.get_object_id().expect("Node is an object"));
// Implemented interfaces resolve in alphabetical name order.
let interface_names: Vec<String> = node
.interfaces
.iter()
.map(|id| schema.interface(*id).name.item.to_string())
.collect();
assert_eq!(interface_names, vec!["Alpha", "Mango", "Zeta"]);
// Directives applied to the type are sorted by name.
let type_directives: Vec<String> =
node.directives.iter().map(|d| d.name.to_string()).collect();
assert_eq!(type_directives, vec!["abc", "zed"]);
let search = schema.field(
schema
.named_field(node_type, "search".intern())
.expect("Node.search exists"),
);
// Field arguments are sorted by name.
let argument_names: Vec<String> = search
.arguments
.iter()
.map(|arg| arg.name.item.to_string())
.collect();
assert_eq!(argument_names, vec!["alpha", "mango", "zebra"]);
// Directives applied to the field are sorted by name too.
let field_directives: Vec<String> = search
.directives
.iter()
.map(|d| d.name.to_string())
.collect();
assert_eq!(field_directives, vec!["abc", "zed"]);
}View on GitHub (pinned to 668b1b85e0)
Solutions
- Confirm the SDL in the test still declares `search(...)` on `type Node` (line ~810 of build_in_memory_schema.rs) and that spelling matches the lookup string exactly.
- Replace the `.expect(...)` with proper handling (`if let Some(id) = schema.named_field(...)` or `.ok_or_else(|| ...)?`) so a missing field produces a descriptive error instead of a bare panic message.
- Check `build_in_memory_schema`'s field-registration path for regressions that drop fields, and verify `schema.get_type("Node")` / `object(...)` return the type you expect before the lookup.
- If the field was intentionally removed, delete or rewrite the assertion to target a field that still exists.
Example fix
// before
let search = schema.field(
schema
.named_field(node_type, "search".intern())
.expect("Node.search exists"),
);
// after
let field_id = schema
.named_field(node_type, "search".intern())
.unwrap_or_else(|| panic!("Node.search missing; Node fields: {:?}", node.fields));
let search = schema.field(field_id); Defensive patterns
Strategy: type-guard
Validate before calling
// Before relying on a field lookup, assert presence:
assert!(
schema.named_field(node_type, "search".intern()).is_some(),
"Node must declare a `search` field"
); Type guard
fn has_field(schema: &Schema, type_: TypeRef, name: &str) -> bool {
schema.named_field(type_, name.intern()).is_some()
} Try / catch
// Rust panics cannot be caught with try/catch; avoid .expect on fallible lookups:
match schema.named_field(node_type, "search".intern()) {
Some(id) => process(schema.field(id)),
None => eprintln!("field `search` not found on type"),
}
// (std::panic::catch_unwind only as a last resort in test harnesses) Prevention
- Never `.expect`/`.unwrap` on Option-returning schema lookups in library or test code without embedding context in the message.
- Keep the SDL fixture and the looked-up names in the same test function and derive one from the other when possible.
- After changing any SDL string in a test, grep the test for `.expect` messages tied to old names.
- Check `get_type`/`object` results before field lookups so failures localize to the actual broken step.
When it happens
Trigger: Calling `schema.named_field(object_type, name)` where the object type has no field with that exact interned name. In this test's context it means `build_in_memory_schema` dropped or failed to register the `search(zebra: Int, alpha: Int, mango: Int): String` field declared on `type Node` in the SDL, e.g. the field was never added, was added to a different type, or the SDL text was edited/renamed without updating the test.
Common situations: Renaming or removing the `search` field in the test SDL while the assertion still looks it up; a regression in the in-memory schema builder that silently drops fields; interning the name with the wrong string ("Search" vs "search"); passing a type handle for a different object than the one declaring the field.
Related errors
- Expected docblocks to only expose object and scalar definiti
- interface B not found
- apple not found
- mango not found
- Expected a key
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/91b9bcc8d3a48ed4.
Report an issue: GitHub.