{"record":{"id":"6b98a77a62657c1f","repo":"projectdiscovery/nuclei","slug":"failed-to-parse-protoset-file-w","errorCode":null,"errorMessage":"failed to parse protoset file: %w","messagePattern":"failed to parse protoset file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/grpc/invoke.go","lineNumber":110,"sourceCode":"// compiled protoset file (read through the local-file-access allowlist) or, when\n// no protoset is provided, from server reflection over the existing connection.\n// The returned cleanup func must be called once the source is no longer needed.\nfunc descriptorSource(ctx context.Context, executionID string, cc *grpc.ClientConn, protosetFile string) (grpcurl.DescriptorSource, func(), error) {\n\tnoop := func() {}\n\tif strings.TrimSpace(protosetFile) != \"\" {\n\t\t// resolve through the local-file-access allowlist: unless -lfa is set,\n\t\t// only files inside the nuclei-templates directory are permitted.\n\t\tnormalized, err := protocolstate.NormalizePathWithExecutionId(executionID, protosetFile)\n\t\tif err != nil {\n\t\t\treturn nil, noop, fmt.Errorf(\"protoset path denied: %w\", err)\n\t\t}\n\t\tdata, err := os.ReadFile(normalized)\n\t\tif err != nil {\n\t\t\treturn nil, noop, fmt.Errorf(\"failed to read protoset file: %w\", err)\n\t\t}\n\t\tfds := &descriptorpb.FileDescriptorSet{}\n\t\tif err := proto.Unmarshal(data, fds); err != nil {\n\t\t\treturn nil, noop, fmt.Errorf(\"failed to parse protoset file: %w\", err)\n\t\t}\n\t\tsrc, err := grpcurl.DescriptorSourceFromFileDescriptorSet(fds)\n\t\tif err != nil {\n\t\t\treturn nil, noop, fmt.Errorf(\"failed to build descriptor source from protoset: %w\", err)\n\t\t}\n\t\treturn src, noop, nil\n\t}\n\n\trefClient := grpcreflect.NewClientAuto(ctx, cc)\n\tcleanup := func() { refClient.Reset() }\n\treturn grpcurl.DescriptorSourceFromServer(ctx, refClient), cleanup, nil\n}\n\n// invokeUnary invokes a unary (or single-response) gRPC method described by src\n// over cc, marshaling the JSON request and formatting the JSON response.\nfunc invokeUnary(ctx context.Context, src grpcurl.DescriptorSource, cc *grpc.ClientConn, method, requestJSON string, headers []string) (string, error) {\n\tbody := strings.TrimSpace(requestJSON)\n\tif body == \"\" {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/grpc/invoke.go#L92-L128","documentation":"The file was read successfully but proto.Unmarshal could not decode it as a protobuf FileDescriptorSet. ProtosetFile must point to a compiled binary descriptor set, not to .proto source text, a JSON descriptor, or any other encoding — the unmarshaler rejects those immediately.","triggerScenarios":"opts.ProtosetFile points at a .proto source file ('syntax = \"proto3\";' text); a .json descriptor or grpcurl text dump; a truncated or base64/gzip-wrapped descriptor that was never decoded back to binary; an empty file.","commonSituations":"Authors assuming the library compiles proto source on the fly; passing descriptor files produced by tooling that emits a different format; hand-editing or re-saving the protoset as text.","solutions":["Compile the schema to a real descriptor set: protoc --descriptor_set_out=acme.protoset --include_imports acme.proto","Sanity-check the artifact: a valid protoset is binary and non-empty, it does not start with 'syntax ='","If you only have .proto source and the target supports reflection, omit ProtosetFile and let the schema come from the server"],"exampleFix":"// before: proto source, not a compiled descriptor set\no.ProtosetFile = 'acme.proto'; // -> failed to parse protoset file\n\n// after: compile first, then reference the binary descriptor\n// shell: protoc --descriptor_set_out=acme.protoset --include_imports acme.proto\no.ProtosetFile = 'acme.protoset';","handlingStrategy":"validation","validationCode":"if (!o.ProtosetFile.endsWith('.protoset')) {\n  // almost certainly raw .proto source: compile it first with\n  // protoc --descriptor_set_out=... --include_imports\n}","typeGuard":"const looksLikeDescriptorSet = (path) => path.endsWith('.protoset');","tryCatchPattern":"try { const c = new grpc.Client(t, o); c.Connect(); }\ncatch (e) { if (/failed to parse protoset/.test(e.message || '')) { /* recompile the descriptor set; or drop ProtosetFile and use reflection */ } }","preventionTips":["Generate descriptor sets only with protoc --descriptor_set_out (binary format)","Never point ProtosetFile at .proto source, JSON descriptors, or base64 blobs","Smoke-test each shipped protoset against a reflection-capable server before release"],"tags":["grpc","protobuf","validation"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}