You’ve created a useful Message object in one .proto file that you’d like to reference in another, perhaps to use it as a field in another Message. You import “foobar.proto”, then use the field foobar.FooField in your dependent Message object, and are greeted with this arcane error:

pub foo_field: ::prost::alloc::vec::Vec<super::foobar::FooField>,
                                                      ^ not found in `super::foobar`

Yikes! How can you be held responsible for this code? It’s being automatically generated!

… from your .proto file.

syntax = "proto3";

package dependent;

import "foobar.proto";

service DependentService {
    rpc ListStuff(ListStuffRequest) returns (stream StreamItem);
}

message StreamItem {
    foobar.FooField foo_field = 1;
}

If you’re encountering this problem, you’ve probably done the same thing I have and I can assure you that it is totally your fault, but it’s pretty easy to resolve.

This problem is tricky to troubleshoot because it’s abstract - at least to me - who super is here. You’ll find that if you change your proto file to try different permutations of your import line like “protoc/foobar.proto” you’ll instead get an immediate import error - clearly your file is being imported correctly, and even a trivial file with continue to trigger this error.

The issue here is where you fold your proto definitions into your Rust code. Typically - if you’ve followed tutorials and examples - you’ll have done this in a types.rs file that might look something like this:

pub mod common {
    tonic::include_proto!("common");
}

pub mod auth {
    tonic::include_proto!("auth");
}

// do not copy this!
pub mod dependent {
    tonic::include_proto!("dependent);
    tonic::include_proto!("foobar");
}

Ready to smack your head? That code you’re getting the error for is included by that tonic::include_proto! macro. super is your types.rs file. If you don’t match your proto package names to the mod names that you include the protocol definitions under, the code won’t be able to find the other packages in the same namespace. Maybe like me you thought you’d be clever and consolidate similar protocols under the same common package name but keep the protocol buffer files separate for clarity in editing. You can’t do that, unfortunately.

Here’s what that has to look like, for this to work:

pub mod common {
    tonic::include_proto!("common")
}

pub mod auth {
    tonic::include_proto!("auth")
}

pub mod dependent {
    tonic::include_proto!("dependent")
}

pub mod foobar {
    tonic::include_proto!("foobar")
}

Now super::foobar will find that pub mod foobar line and the code will compile.