49

I am trying to create a VSCode extension. This extension provides two commands, never mind their implementation:

export function activate(context: ExtensionContext) {

    const provider = new ContentProvider();
    const providerRegistrations = Disposable.from(
        workspace.registerTextDocumentContentProvider(ContentProvider.scheme, provider)
    );

    // Open the dynamic document, and shows it in the next editor
    const openMyExtensionCommandRegistration = commands.registerTextEditorCommand('extension.openMyExtension', editor => {
        // Activate the extension and do something
    });

    const useMyExtensionCommandRegistration = commands.registerTextEditorCommand('extension.useMyExtension', editor => {
        // Do something
    });

    context.subscriptions.push(
        provider,
        openMyExtensionCommandRegistration,
        useMyExtensionCommandRegistration,
        providerRegistrations
    );
}

And this is a part of my package.json file:

"activationEvents": [
        "onCommand:extension.openMyExtension"
    ],
    "main": "./out/extension",
    "contributes": {
        "commands": [
            {
                "command": "extension.openMyExtension",
                "title": "Open my extension",
                "category": "MyExtension"
            },
            {
                "command": "extension.useMyExtension",
                "title": "Do something with my extension",
                "category": "MyExtension"
            }
        ],

The first command, which is supposed to activates my extension, works. It appears in the command palette, and actually does what it is supposed to do when invoked.

The second command however, despite appearing in the command palette, raise the following error message when called:

command 'extension.useMyExtension' not found

I find it weird that my first command works fine but not the second since the code is quite similar. Any ideas why?

Note that I obviously changed some variable names, I double checked for typos in the real code.

Gama11
  • 31,714
  • 9
  • 78
  • 100
Eldy
  • 1,027
  • 1
  • 13
  • 31
  • Have you checked if it works when you change `registerTextEditorCommand` to `registerCommand`? I'm just curious about it. Your code looks alright to me, too. – HaaLeo Mar 30 '18 at 18:16
  • I am still investigating on what caused the issue exactly, but to sum it up, the command that was supposed to compile the TypeScript into JavaScript was not working on my machine. I figured that by looking at the JavaScript generated sources. – Eldy Apr 01 '18 at 08:31
  • Can you try creating two different extensions with each command and see if that works? This will give an idea if multiple commands in a single extension are not causing any problem. – RKS_Code Apr 06 '18 at 15:00
  • 3
    I was able to fix this issue by manually compiling the Typescript source (by running `tsc -p ./` into my root folder). This command should be ran automatically when debugging, however, I was still not able to find why it was not the case on my machine. – Eldy Apr 06 '18 at 15:13
  • 2
    @Eldy I just had the exact same issue (my extension.ts file was not being rebuilt when hitting F5) and I was seeing the error that a newly registered command was not found. Running `tsc -p ./` also fixed the problem for me! Thanks for sharing your resolution. – Tom Jan 06 '19 at 11:26
  • Since my comment helped someone, I will to post it as an answer to give it more visibility. – Eldy Jan 08 '19 at 13:30
  • My extension is working fine when debugging but not working when published, extension.command not found, please help – Huzaifa Ahmed Nov 06 '20 at 12:08
  • Judging from your solution I would say you forgot to add `onCommand:extension.useMyExtension` inside the `activationEvents` **in this question**. I believe in your real code you had that. – DarkTrick Oct 08 '21 at 23:04

11 Answers11

41

You need to add all registered commands to the activationEvents list in package.json so that they are available on invocation. Update your package.json as such:

{
    ...
    "activationEvents": [
        "onCommand:extension.openMyExtension",
        "onCommand:extension.useMyExtension"
    ]
    ...
}

You can find more details on activation events in the official VSCode Documentation.

TheLandolorien
  • 568
  • 4
  • 11
  • 1
    I guess this is no longer required if you have added the command inside contributes/commands section in package.json as VSCode automatically generates this. – Sachin Jain Apr 20 '23 at 14:23
12

I had the same issue. Everything was configured correctly but it turned out my package.json was missing one dependency. That caused the extension to fail loading and consequently the command not having been registered correctly at runtime.

To find out what is wrong with your code, open up the Help > Toggle Developer Tools and look for errors in the console.

Bart Theeten
  • 551
  • 6
  • 6
5

you have not activated the extension in activationEvents:

"activationEvents": [
    "onCommand:extension.useMyExtension"
],
TheLandolorien
  • 568
  • 4
  • 11
Jackie
  • 25,199
  • 6
  • 33
  • 24
4

In case anyone made the same mistake as I did...

So if it compiles successfully, but complains command could not found, check:

  1. In the extension debug window, check the console logs from Help > Toggle Developer Tools (From @Bart Theeten). There's a high chance of JS error you've not noticed.

  2. Whether all the commands are added to package.json

"contributes": {
    "commands": [ ... ]
}
  1. Whether the command is registered with
context.subscriptions.push(
    vscode.commands.registerCommand('command_name', callbackFunc)
);
  1. Finally, check the production bundle setting <- this is the one that caused me headache

My extension was made with Typescript, and bundled by Webpack + ts-loader. I introduced an interesting conditionally load module feature, which will need to require module from a dynamic path like /module/<version>. That creates several interesting problems:

First is a wrong __dirname, __filename globals that only happens when using webpack to pack NodeJS apps(I got / value for __dirname). I have to set webpack.config.js with:

module.exports = {
  node: false
}

To disable the webpack nodeJS global mocks. (reference)

Secondly, the modules path restrictions that we easily forgot:

The absolute path import may not work, the relative path also could not exceed the scope you've set somewhere ‍♀️. Example:

// tsconfig.json
{
  "compilerOptions": {
    "outDir": "lib"
  },
  "include": ["src"]
}
// src/index.ts
require('../external/test')

The require path will be processed by ts-loader and webpack, it could not recognize this module path unless you use path aliases to tell them where these files are located.

And the dynamic import path cannot be dynamic after compile:

require(`./${dir}/module`) // may not work
import(`./${dir}/module`)  // may not work

Well, the reason is compiler loaders may do some processing with the path, if it is a simple static string, it could replace it with the right one but if it is a runtime value it couldn't. I am sorry but I easily forgot this since it's a function syntax!

And you know what's worse? The worse case is I get the path thing works for me but not working for others. Because the hack introduced the absolute path that only exists on my environment... Well for this, I have to say try avoid the absolute path.

Jennie Ji
  • 769
  • 5
  • 13
3

Since my comment helped someone, I would like to post it as an answer to give it more visibility:

I was able to fix this issue by manually compiling the Typescript source (by running tsc -p ./ into my root folder). This command should be ran automatically when debugging, however, I was still not able to find why it was not the case on my machine.

Eldy
  • 1,027
  • 1
  • 13
  • 31
1

I just encountered this problem after following the 'Your first extension tutorial'. The problem came from the vscode version used in the package.json: I use vscode 1.79.2 but yo generated an extension for vscode 1.80.

In the package.json file, I changed:

  "engines": {
    "vscode": "^1.80.0"
  },

to match the exact version of my vscode instance:

  "engines": {
    "vscode": "^1.79.2"
  },

I also changed this dependency following the same reasoning:

  "devDependencies": {
    "@types/vscode": "^1.79.2",

I ran npm install and then running the extension now works.

ARno
  • 314
  • 3
  • 14
  • Thanks, this was the problem for me. I instead updated the vs code itself to the latest version. – III_phr Jul 20 '23 at 11:54
0

My issue is I was running Cmder as my VS Code terminal. When I started debugging, the build would never complete - you can monitor Running Tasks from the bottom toolbar. When I looked at the task being run, I saw this:

Executing task: npm run watch <

VS Code is attempting to run the watch script but it never finished - I'm guessing some syntactical issue is at work here.

Anyway, while compiling does work, I'd recommend running the watch script instead so that your extension will re-compile with every file change:

npm run watch

You should now be able to run your extension in your extension host via F5 without having to re-compile constantly. (You'll still need to reload your host though)

Mister Epic
  • 16,295
  • 13
  • 76
  • 147
0

I'm adding this answer for anyone who might experience this behavior for the same reason I did because it took me quite some time to realize what was happening.

I use PowerShell as my default terminal and had my profile configured to set the path of new shells (using Set-Location) to a specific folder for convenience on other development work I'm doing.

When pressing F5 to launch my extension, VS Code was attempting to run the compile command from this directory rather than my project directory, which failed of course.

This failure was obvious in the C:\Users\<your_user_name>\AppData\Roaming\npm-cache\_logs files once I realized to look there.

I removed the path setting from my PowerShell profile and VS Code extension building worked as expected.

intheweeds
  • 79
  • 1
  • 2
0

I built my extension with vsce package and installed it by vsix file.

I had the same issue and fixed it by running npm install in ".vscode/extensions/EXTENSION_NAME" folder. EXTENSION_NAME is the name of the extension.

I found the solution in a github issue

kiritoXF
  • 181
  • 5
  • Did not work for me. Besides, note, that `.vscode/extensions/EXTENSION_NAME` is not the directory inside your project workspace, but it's the global vscode extension directory. On Linux it would be `~/.vscode/extensions/EXTENSION_NAME` – DarkTrick Oct 08 '21 at 22:52
  • Why not just have `node_modules` included in your package, as they recommend in the issue? – Mugen Dec 30 '21 at 08:23
0

Looked at all the above answers and they did not do it for me. Here is what I did together that did for me: 1.

 output: {
    // the bundle is stored in the 'dist' folder (check package.json),  -> https://webpack.js.org/configuration/output/
    path: path.resolve(__dirname, 'dist'),
    filename: 'extension.js',
    libraryTarget: 'commonjs2',
    devtoolModuleFilenameTemplate: '../[resource-path]'
  },

I added libraryTarget to commonjs2

  1. I removed .ts from my extensions
resolve: {
...
extensions: ['.js', '.mjs'],
}

notice extensions no longer has a .ts. This required me to add .js to all of my relative import paths.

  1. I had an improper import path it was importing from @library-name/xyz/xyz instead of @libary-name. Make sure to double check this one.

Much love to anyone else who might be coming across one of those most difficult software problems of their career ❤️

Charlie-Greenman
  • 1,469
  • 1
  • 16
  • 36
  • It would be helpful if you included the file type or name in each of your examples. Just from example 1) and 2) it is rather unclear what files we are talking about. – Daniel Jun 30 '22 at 06:47
  • this was so long ago, it might be useful to delete my answer. best i can do for now all things considered time wise – Charlie-Greenman Jul 05 '22 at 11:18
-3

Your problem looks similar to this issue: https://github.com/Microsoft/vscode/issues/25026