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

Type::Path is expected

Error message

Type::Path is expected

What it means

`get_type_from_possible_dyn_type` only understands plain type paths (`std::path::Type::Path`). If the inner return type of a native-bridge function is any other syntax form — a reference `&T`, a slice `[T]`, a tuple, a trait object directly, a pointer, or `impl Trait` — the macro cannot generate deserialization code and throws 'Type::Path is expected'.

Source

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

                            original_type,
                            dynamic_container_path: Some(dynamic_container_path),
                        })
                    } else {
                        Ok(NativeOutputParams {
                            type_path: tp.path.clone(),
                            original_type: tp.path.clone(),
                            dynamic_container_path: None,
                        })
                    }
                } else {
                    Ok(NativeOutputParams {
                        type_path: tp.path.clone(),
                        original_type: tp.path.clone(),
                        dynamic_container_path: None,
                    })
                }
            }
            _ => Err(syn::Error::new(tp.span(), "Type::Path is expected")),
        }
    }

    fn get_dyn_type_for_deserialize(args: &PathArguments) -> Option<Path> {
        match args {
            syn::PathArguments::AngleBracketed(args) => {
                if args.args.is_empty() {
                    return None;
                }
                let arg = args.args.first().unwrap();

                match arg {
                    syn::GenericArgument::Type(tp) => match tp {
                        Type::TraitObject(to) => {
                            let type_param_bound = to.bounds.first().unwrap();
                            match type_param_bound {
                                syn::TypeParamBound::Trait(trait_bound) => {
                                    let mut path = trait_bound.path.clone();

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Change the inner type to a named path type: `String` instead of `&str`, `Vec<u8>` instead of `[u8]`, a struct instead of a tuple.
  2. For dynamic dispatch, use a smart-pointer path form the macro understands, e.g. `Box<dyn MyTrait>` or `Arc<dyn MyTrait>` (it detects Rc/Arc/Box + trait objects).
  3. Return owned data only — the bridge serializes values across FFI, so borrowed/pointer types are unsupported.

Example fix

// before
fn native_fn() -> Result<&str> { ... }
// after
fn native_fn() -> Result<Option<String>> { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure inner return type is a named path type (no refs/slices/tuples/ptrs):
fn inner_is_path_type(sig: &str) -> Result<(), String> {
    let bad = ["&", "[", "(", "*", "impl ", "dyn "];
    if let Some(inner) = sig.strip_prefix("Result<Option<") {
        if bad.iter().any(|b| inner.trim_start().starts_with(b)) {
            return Err(format!("inner type must be a path type: {sig}"));
        }
    }
    Ok(())
}

Type guard

fn is_named_path_type(t: &str) -> bool { let t = t.trim(); t.chars().next().map_or(false, |c| c.is_alphabetic() || c == '_') && !t.starts_with("impl ") && !t.starts_with("dyn ") && !t.starts_with('&') }

Prevention

When it happens

Trigger: Declaring a native-bridge return like `Result<&str>`, `Result<[u8; N]>`, `Result<(A, B)>`, `Result<*const T>`, or `Result<impl Trait>`; anything whose inner type is not a named path type.

Common situations: Copying idiomatic Rust signatures (references, tuples, slices) into macro-annotated native functions; trying to return borrowed data across the FFI boundary; returning trait objects directly instead of `Box<dyn Trait>` path forms.

Related errors


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