{"record":{"id":"0ef93b1b2b94bca7","repo":"cube-js/cube","slug":"type-path-is-expected","errorCode":null,"errorMessage":"Type::Path is expected","messagePattern":"Type::Path is expected","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"rust/cube/cubesqlplanner/nativebridge/src/lib.rs","lineNumber":371,"sourceCode":"                            original_type,\n                            dynamic_container_path: Some(dynamic_container_path),\n                        })\n                    } else {\n                        Ok(NativeOutputParams {\n                            type_path: tp.path.clone(),\n                            original_type: tp.path.clone(),\n                            dynamic_container_path: None,\n                        })\n                    }\n                } else {\n                    Ok(NativeOutputParams {\n                        type_path: tp.path.clone(),\n                        original_type: tp.path.clone(),\n                        dynamic_container_path: None,\n                    })\n                }\n            }\n            _ => Err(syn::Error::new(tp.span(), \"Type::Path is expected\")),\n        }\n    }\n\n    fn get_dyn_type_for_deserialize(args: &PathArguments) -> Option<Path> {\n        match args {\n            syn::PathArguments::AngleBracketed(args) => {\n                if args.args.is_empty() {\n                    return None;\n                }\n                let arg = args.args.first().unwrap();\n\n                match arg {\n                    syn::GenericArgument::Type(tp) => match tp {\n                        Type::TraitObject(to) => {\n                            let type_param_bound = to.bounds.first().unwrap();\n                            match type_param_bound {\n                                syn::TypeParamBound::Trait(trait_bound) => {\n                                    let mut path = trait_bound.path.clone();","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube/cubesqlplanner/nativebridge/src/lib.rs#L353-L389","documentation":"`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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the inner type to a named path type: `String` instead of `&str`, `Vec<u8>` instead of `[u8]`, a struct instead of a tuple.","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).","Return owned data only — the bridge serializes values across FFI, so borrowed/pointer types are unsupported."],"exampleFix":"// before\nfn native_fn() -> Result<&str> { ... }\n// after\nfn native_fn() -> Result<Option<String>> { ... }","handlingStrategy":"validation","validationCode":"// Ensure inner return type is a named path type (no refs/slices/tuples/ptrs):\nfn inner_is_path_type(sig: &str) -> Result<(), String> {\n    let bad = [\"&\", \"[\", \"(\", \"*\", \"impl \", \"dyn \"];\n    if let Some(inner) = sig.strip_prefix(\"Result<Option<\") {\n        if bad.iter().any(|b| inner.trim_start().starts_with(b)) {\n            return Err(format!(\"inner type must be a path type: {sig}\"));\n        }\n    }\n    Ok(())\n}","typeGuard":"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('&') }","tryCatchPattern":null,"preventionTips":["Use `String`/`Vec<u8>`/structs instead of `&str`, slices, tuples, or raw pointers in returns.","For dynamic dispatch use `Box<dyn Trait>` / `Arc<dyn Trait>` path forms, which the macro recognizes.","Remember FFI bridges serialize owned values — design return types accordingly."],"tags":["rust","proc-macro","compile-time","type-signature","ffi"],"backgroundTag":"unsupported-ffi-type","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}