-
Notifications
You must be signed in to change notification settings - Fork 16k
Description
What version of protobuf and what language are you using?
Version: main/v3.6.0/v3.5.0 etc. (NOTE: please try updating to the latest version of protoc/runtime possible beforehand to attempt to resolve your problem)
Language: C++/Java/Python/C#/Ruby/PHP/Objective-C/Javascript
v33.4; Rust originally, minimal repro here with C++
What operating system (Linux, Windows, ...) and version?
Windows
What runtime / compiler are you using (e.g., python version or gcc version)
protoc --version
libprotoc 33.4
What did you do?
Steps to reproduce the behavior:
- On Windows: Install protoc, add to the system PATH with a symbolic link. Ensure it is placed in an arbitrary location that isn't sharing current directory or parent directory with protoc.exe
- Compile a minimal proto that references a bundled file, without additional include dirs provided:
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package fake;
service FooService {
rpc Foo(FooMessage) returns (FooResult);
}
message FooMessage {
bytes payload = 1;
// Validates that the bundled includes are available
google.protobuf.Timestamp submit_time = 2;
}
message FooResult {
string message = 1;
}using the command:
protoc .\src\fake-crate\protos\foo.proto --cpp_out temp
- Remove the symlink and add protoc.exe parent direcotry directly to PATH. Run the same command, observe it now passes.
What did you expect to see
Protoc finds the bundled definition google/protobuf/timestamp.proto and successfully compiles
What did you see instead?
google/protobuf/timestamp.proto: File not found.
src/fake-crate/protos/foo.proto:3:1: Import "google/protobuf/timestamp.proto" was not found or had errors.
src/fake-crate/protos/foo.proto:14:3: "google.protobuf.Timestamp" is not defined.
Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).
Anything else we should know about your project / environment
I originally encountered this because of a WinGet bug that was improperly tagging the package leading to a symlink being used. I raised a separate issue there that has unblocked us, but sincethe functions used on other platforms will resolve symlinks, I believe this is an oversight on the Windows side:
- Mac:
realpath - Else:
readlink
The Windows implementation is using GetModuleFileNameA, which isn't resolving the symlink. Instead, that result should probably then be passed to GetFinalPathNameByHandleA in order to resolve it.
From repro machine:
PS C:\Users\chhenk> ls ~\AppData\Local\Microsoft\WinGet\Links
Directory: C:\Users\chhenk\AppData\Local\Microsoft\WinGet\Links
Mode LastWriteTime Length Name
---- ------------- ------ ----
la--- 1/26/2026 5:32 PM 0 protoc.exe ->
C:\Users\chhenk\AppData\Local\Microsoft\WinGet\Packages\Google.Protobuf_Microsoft.Winget.Source_8wekyb3d8bbwe\bin\protoc.exe
PS C:\Users\chhenk> $env:PATH -split ';' | Where-Object { $_ -match 'winget' }
C:\Users\chhenk\AppData\Local\Microsoft\WinGet\Links
Whereas when I have a direct reference in the PATH like so, it works as expected:
$env:PATH -split ';' | Where-Object { $_ -match 'winget' }
C:\Users\chhenk\AppData\Local\Microsoft\WinGet\Packages\Google.Protobuf_Microsoft.Winget.Source_8wekyb3d8bbwe\bin