cube-js/cube · error · syn::Error

NativeBridgeStatic requires a struct with named fields

Error message

NativeBridgeStatic requires a struct with named fields

What it means

`NativeBridgeStatic` requires a struct with named fields because the macro generates metadata keyed by field name. This error fires for structs with unnamed (tuple) fields or unit structs, since there are no names to emit into the static field table.

Source

Thrown at rust/cube/cubesqlplanner/nativebridge/src/lib.rs:915

    TokenStream::from(expanded)
}

fn collect_static_field_meta_entries(
    input: &DeriveInput,
) -> syn::Result<Vec<proc_macro2::TokenStream>> {
    let data = match &input.data {
        Data::Struct(d) => d,
        _ => {
            return Err(syn::Error::new(
                input.span(),
                "NativeBridgeStatic can only be derived for structs",
            ))
        }
    };
    let fields = match &data.fields {
        Fields::Named(named) => &named.named,
        _ => {
            return Err(syn::Error::new(
                input.span(),
                "NativeBridgeStatic requires a struct with named fields",
            ))
        }
    };

    let mut entries = Vec::new();
    for field in fields {
        let ident = field.ident.as_ref().unwrap();
        let name_str = ident.to_string();
        let mut js_name: Option<String> = None;
        let mut skip = false;
        for attr in &field.attrs {
            if attr.path().is_ident("serde") {
                // Best-effort: serde supports many options with `= value` shapes
                // (e.g. `default = "fn"`) that parse_nested_meta cannot pass
                // through to our callback unchanged, so we swallow errors and
                // pick up only the `rename = "..."` shape we care about.

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Give the struct named fields: `struct Foo { value: u32 }` instead of `struct Foo(u32)`.
  2. Unwrap newtype wrappers and derive on the inner named-field struct.
  3. Remove the derive if tuple/unit shape is required and generate metadata manually.

Example fix

// before
#[derive(NativeBridgeStatic)]
struct Config(u32);
// after
#[derive(NativeBridgeStatic)]
struct Config { value: u32 }
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the struct uses named fields, not tuple/unit form:
fn has_named_fields(decl: &str) -> bool {
    let body = decl.split('{').nth(1).unwrap_or("");
    body.contains(':') // named field like `value: u32`
}

Type guard

fn is_named_field_struct(kind: &str, has_brace_body: bool) -> bool { kind == "struct" && has_brace_body }

Prevention

When it happens

Trigger: Applying `#[derive(NativeBridgeStatic)]` to a tuple struct (`struct Foo(u32, String)`) or a unit struct (`struct Foo;`).

Common situations: Using tuple structs for convenience (e.g. newtypes) while keeping the derive; converting a named struct into a newtype wrapper; auto-generated tuple structs from other macros.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/4ae832721ccb461b. Report an issue: GitHub.