facebook/relay · error

Expected an object key or null

Error message

Expected an object key or null

What it means

write_argument_value serializes constant argument values into the generated artifact. When it encounters a list element that is neither a storage-key object nor null, it panics. Before reaching this branch, Variables and object values are filtered out; the code only supports serializing lists whose items reduce to an object (used for static storage keys) or null, so any other primitive kind inside that list position violates an internal invariant.

Source

Thrown at compiler/crates/relay-codegen/src/printer.rs:855

            .expect("Expected `items` to exist")
            .value;
        let array = builder.lookup(items.assert_key()).assert_array();

        f.push('[');
        let mut after_first = false;
        for key_or_null in array {
            match key_or_null {
                Primitive::Null => {}
                Primitive::Key(key) => {
                    if after_first {
                        f.push(',');
                    } else {
                        after_first = true;
                    }
                    let object = builder.lookup(*key).assert_object();
                    write_argument_value(f, builder, object)?;
                }
                _ => panic!("Expected an object key or null"),
            }
        }
        f.push(']');
    } else {
        // We filtered out Variables, here it should only be ObjectValue
        let fields = &arg
            .iter()
            .find(|entry| entry.key == CODEGEN_CONSTANTS.fields)
            .expect("Expected `fields` to exist")
            .value;
        let fields = builder.lookup(fields.assert_key()).assert_array();

        f.push('{');
        for field in fields {
            let field = builder.lookup(field.assert_key()).assert_object();
            let name = &field
                .iter()
                .find(|entry| entry.key == CODEGEN_CONSTANTS.name)

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Simplify the list argument passed to @static_arg/@arguments so its elements are supported (objects or null) — e.g. use plain constant values instead of nested variables
  2. Remove variables from list-typed arguments that feed static storage key generation; hoist them as separate arguments
  3. Verify which fragment/argument triggers it by bisecting documents, and check the IR transform output for that node
  4. Upgrade or fix the compiler so list argument handling in write_static_storage_key matches the emitted IR

Example fix

// before
query($ids: [ID]) @static_arg(key: "ids", value: $ids) { ... }
// after
query @static_arg(key: "ids", value: ["123", "456"]) { ... }
Defensive patterns

Strategy: validation

Validate before calling

function validateStaticArgValue(value) {
  if (Array.isArray(value)) {
    return value.every(v => v === null || (v && typeof v === 'object' && !Array.isArray(v)) || validateStaticArgValue(v));
  }
  return true;
}
if (!validateStaticArgValue(staticArgValue)) throw new Error('static arg list items must be objects or null');

Type guard

const isStorageKeyListItem = (v) =>
  v === null || (typeof v === 'object' && v !== null && !Array.isArray(v));

Try / catch

try {
  generateArtifacts();
} catch (e) {
  if (String(e).includes('Expected an object key or null')) {
    // simplify the list argument feeding @static_arg
  }
  throw e;
}

Prevention

When it happens

Trigger: Printing an argument value that is a list containing an unexpected element kind at that position — e.g. a variable, scalar, or enum element where the builder expected a nested object (for @static_arg/StorageKey emission) or null; corrupted IR where list item filtering didn't happen as designed.

Common situations: Using @static_arg/@arguments with list arguments containing items the codegen cannot reduce; custom transforms injecting non-object list elements into static argument positions; compiler version mismatches producing IR the printer doesn't expect.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/91c3bad5ebb81222. Report an issue: GitHub.