Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Extension - Error in https.request - The "listener" argument must be of type Function. Received type object #93167

Closed
samusstrike opened this issue Mar 22, 2020 · 9 comments
Assignees
Labels
bug Issue identified by VS Code Team member as probable bug proxy Issues regarding network proxies verified Verification succeeded
Milestone

Comments

@samusstrike
Copy link

Version: 1.43.1 (user setup)
Commit: fe22a96
Date: 2020-03-18T07:01:20.184Z
Electron: 7.1.11
Chrome: 78.0.3904.130
Node.js: 12.8.1
V8: 7.8.279.23-electron.0
OS: Windows_NT x64 10.0.17134

Background:
I'm developing a VSCode extension which makes web requests to a server. The extension is installed on my instance of VSCode when the error is produced. I have not see the error while debugging the extension.

Steps to Reproduce:

This problem is hard to reproduce. Using the code below, the error is randomly reproduced. Once it occurs, it will continue to occur until I restart VSCode.

I believe the error is occurring due to this line:
https.request(url, options, (res) => {...})

I figured maybe the VSCode API is taking a wrong path every once in a while and does not properly handle the signature overloads in all cases. It seems that sometimes the API expects the second parameter to always be a function.

Based on this hypothesis, I changed the code to nest the URL content into the options parameter and only pass https.request(options, function). I have not reproduced the error in a week since I modified the code in this way. I was reproducing the error daily, with the same rate of usage.

Here are the signatures for Node https.request:
https.request(options[, callback])
https.request(url[, options][, callback])

Please let me know if I can provide more information.

const https = require('https')

/**
 * @param {string} url https.request url
 * @param {RequestOptions} options https.request options
 * @returns {Promise} Resolves with the request and response object.
 */
function makeRequest(url, options) {
	return new Promise((resolve, reject) => {
		const req = https.request(url, options, (res) => {
			const chunks = []
			res.on('data', (chunk) => {
				chunks.push(chunk)
			})
			res.on('end', () => {
				if (res.statusCode !== constants.statusCodes.ok) {
					reject(new Error(`Error accessing URL ${url}. StatusCode: ${res.statusCode}`))
					return
				}
				res.body = Buffer.concat(chunks).toString()
				resolve({
					req,
					res
				})
			})
		})

		if (options.body) {
			req.write(options.body)
		}
		req.on('error', (e) => {
			reject(e)
		})
		req.end()
	})
}

Stack trace:
onDidChangeNotification (notificationsAlerts.ts:40)
(anonymous) (notificationsAlerts.ts:26)
fire (event.ts:587)
addNotification (notifications.ts:183)
notify (notificationService.ts:101)
(anonymous) (mainThreadMessageService.ts:83)
_showMessage (mainThreadMessageService.ts:44)
$showMessage (mainThreadMessageService.ts:38)
_doInvokeHandler (rpcProtocol.ts:398)
_invokeHandler (rpcProtocol.ts:383)
_receiveRequest (rpcProtocol.ts:299)
_receiveOneMessage (rpcProtocol.ts:226)
(anonymous) (rpcProtocol.ts:101)
fire (event.ts:587)
fire (ipc.net.ts:453)
_receiveMessage (ipc.net.ts:733)
(anonymous) (ipc.net.ts:592)
fire (event.ts:587)
acceptChunk (ipc.net.ts:239)
(anonymous) (ipc.net.ts:200)
t (ipc.net.ts:28)
emit (events.js:203)
addChunk (_stream_readable.js:295)
readableAddChunk (_stream_readable.js:276)
Readable.push (_stream_readable.js:210)
onStreamRead (internal/stream_base_commons.js:166)

Does this issue occur when all extensions are disabled?: n/a I could not do this since my extension is the one with the error.

@gjsjohnmurray
Copy link
Contributor

@chrmarti could this be related to the magic that allows extensions to use a proxy if a site has one?

@chrmarti
Copy link
Collaborator

@samusstrike What are url and options when this fails?

@chrmarti chrmarti added proxy Issues regarding network proxies info-needed Issue requires more information from poster labels Mar 24, 2020
@samusstrike
Copy link
Author

Here's an example of the URL and options provided to https.request. The "RequestOptions" type is that of the Node JS http RequestOptions: https://nodejs.org/docs/latest-v12.x/api/http.html#http_http_request_url_options_callback

Note the URL and options are the same in the case of success or failure.

const url = "https://hostName/app/request?login=true"
/**
 * @type {RequestOptions}
 */
const options = {
	method: "GET",
	headers: {
		username: "asdf",
		password: "12345"
	}
}
const req = https.request(url, options, (res) => {
	//...
})

@chrmarti
Copy link
Collaborator

Could you wrap your code in a try-catch and log the error with its stacktrace? (The stacktrace you posted shows the notification's code path.)

@samusstrike
Copy link
Author

I will work on getting the results. I am reverting to using my old code on my custom extension. It may take me a day or two to get the repro results due to the apparent random behavior. Thanks!

@samusstrike
Copy link
Author

I created an independent extension with this repro: https://github.com/samusstrike/vscodeExtensionRequestIssue.git

After a lot of debugging, I was able to identify an exact repro case. You can choose to use the repository above and use the extension debugger. Or you can use the compiled vsix file on the repo.

Instructions to reproduce using vsix file:

  1. Disable all extensions

    • To rule out other extensions causing the issue.
  2. Install the extension https://github.com/samusstrike/vscodeExtensionRequestIssue/raw/master/extrequesttest-0.0.1.vsix

    • This contains the command to trigger the https.request
  3. Open VSCode (only the one extension above enabled)

  4. Execute the command "vscodeExtTest.testRequestWithIssue"
    Result: No error should occur

  5. Install extension "SQL Server (mssql)" "ms-mssql.mssql"

  6. Open a new editor tab and set the language to SQL

    • This is the key to the randomness. If a file is open with the SQL language set, it will trigger the mssql extension to do black magic.
  7. Execute the command "vscodeExtTest.testRequestWithIssue"
    Result: The error will occur: "The "listener" argument must be of type Function. Received type object"

  8. Execute the command "vscodeExtTest.testRequestWithoutIssue"

    • This is to show that not passing the URL as the first argument to https.request() will allow the code to work.
      Result: No error should occur.

The following is copied from the console.

TMScopeRegistry.ts:45 Overwriting grammar scope name to file mapping for scope source.sql.
Old grammar file: file:///c%3A/Users/user/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/extensions/sql/syntaxes/sql.tmLanguage.json.
New grammar file: file:///c%3A/Users/user/.vscode/extensions/ms-mssql.mssql-1.9.0/syntaxes/SQL.plist
register @ TMScopeRegistry.ts:45
console.ts:137 [Extension Host] logFile for SqlToolsResourceProviderService.exe is c:\Users\user\AppData\Roaming\Code\logs\20200325T031000\exthost1\ms-mssql.mssql\resourceprovider.log
console.ts:137 [Extension Host] This process (ui Extenstion Host) is pid: 45776
console.ts:137 [Extension Host] Old log files deletion report: {}
console.ts:137 [Extension Host] The "listener" argument must be of type Function. Received type object
t.log @ console.ts:137
console.ts:137 [Extension Host] Trace: Repro test	at Object.testRequest (c:\Users\user\.vscode\extensions\test.extrequesttest-0.0.1\app.js:119:11)
t.log @ console.ts:137
notificationsAlerts.ts:40 Error occurred: The "listener" argument must be of type Function. Received type object
onDidChangeNotification @ notificationsAlerts.ts:40

@chrmarti
Copy link
Collaborator

This is an issue with agent-base 4.3.0 not supporting the 3-argument request() added in Node.js v10.9.0 (TooTallNate/node-agent-base#29):
https://github.com/TooTallNate/node-agent-base/blob/560f111674af84dec46a4c3070ddf3b22edd3e76/patch-core.js#L13

agent-base 4.3.0 patches the http/s modules, so any extension loading that module will side-effect all other extensions.

I see agent-base 4.3.0 in use also in other extensions. As a workaround we can hand out copies of http/s to extensions, so they end up modifying their own copy and won't affect others.

@chrmarti chrmarti added bug Issue identified by VS Code Team member as probable bug and removed info-needed Issue requires more information from poster labels Mar 27, 2020
@chrmarti chrmarti added this to the March 2020 milestone Mar 27, 2020
@chrmarti
Copy link
Collaborator

@samusstrike Thanks for the sample to reproduce the issue!

@samusstrike
Copy link
Author

@chrmarti I'm glad it helped. Thank you for your time looking into this. I'm glad there's a workaround for now.

@connor4312 connor4312 added the verified Verification succeeded label Apr 3, 2020
@github-actions github-actions bot locked and limited conversation to collaborators May 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue identified by VS Code Team member as probable bug proxy Issues regarding network proxies verified Verification succeeded
Projects
None yet
Development

No branches or pull requests

4 participants