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

Return type should be {}

Error message

Return type should be {}

What it means

get_output_for_deserializer requires each bridged method to declare an explicit return type, because the macro must build a deserializer for the concrete output shape (Result<_>, Option<_>, Vec<_> wrappers are tracked via `optional`/`vec`). A bare `fn f(&self);` with no `-> T` (ReturnType::Default) gives the macro nothing to deserialize, so it fails with the computed expected type in the message.

Source

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

                }
            }
        }
        Ok(method_params)
    }
    fn get_output_for_deserializer(
        tp: &ReturnType,
        optional: bool,
        vec: bool,
    ) -> syn::Result<NativeOutputParams> {
        let mut expected_type = "Result<_>".to_string();
        if optional {
            expected_type = expected_type.replace("_", "Option<_>");
        }
        if vec {
            expected_type = expected_type.replace("_", "Vec<_>");
        }
        let s = match tp {
            ReturnType::Default => Err(syn::Error::new(
                tp.span(),
                format!("Return type should be {}", expected_type),
            )),
            ReturnType::Type(_, tt) => match tt.as_ref() {
                syn::Type::Path(tp) => {
                    let segs = &tp.path.segments;
                    Self::get_deserializer_output_for_result(segs, optional, vec, &expected_type)
                }
                _ => Err(syn::Error::new(
                    tp.span(),
                    format!("Return type should be {}", expected_type),
                )),
            },
        };
        s
    }

    fn get_deserializer_output_for_result(

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add an explicit return type to the method — every bridged method must return something, normally `Result<_>`.
  2. Use `Result<Option<T>>` or `Result<Vec<T>>` when optional/collection outputs are needed, since those shapes are explicitly supported.
  3. Never leave the return type off; even unit-returning methods must be changed to return a Result.

Example fix

// before
#[native_bridge]
trait MyService {
    fn query(&self);
}

// after
#[native_bridge]
trait MyService {
    fn query(&self) -> Result<String>;
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject methods with no return type before building the service
fn has_return_type(sig: &str) -> bool {
    sig.contains("->")
}
// assert!(has_return_type("fn query(&self) -> Result<String>;"));

Prevention

When it happens

Trigger: Declaring a native_bridge trait method without a return type, e.g. `fn execute(&self);` — the macro then reports `Return type should be Result<_>` (or the Option/Vec-augmented expectation).

Common situations: Writing RPC-style methods that 'return nothing' out of habit, porting plain Rust traits into a native_bridge service without adding Result returns.

Related errors


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