Repository: promptfoo/promptfoo
Issue: CustomProvider: ERR_UNSUPPORTED_ESM_URL_SCHEME
Root cause: Environment Incompatibility

OS: Windows 10
node: 21.7.2
promptfoo: 0.51.0

When I try to use a custom provider (I think I have implemented it according to examples) then I get an error

```
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
    at throwIfUnsupportedURLScheme (node:internal/modules/esm/load:239:11)
    at defaultLoad (node:internal/modules/esm/load:130:3)
    at ModuleLoader.load (node:internal/modules/esm/loader:403:13)
    at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:56)
    at new ModuleJob (node:internal/modules/esm/module_job:67:26)
    at #createModuleJob (node:internal/modules/esm/loader:297:17)
    at ModuleLoader.getJobFromResolveResult (node:internal/modules/esm/loader:254:34)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:235:17)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ModuleLoader.import (node:internal/modules/esm/loader:322:23) {
  code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
}
```

```
promptfoo.config

prompts: "{{question}}"
providers: [customProvider.js]
tests: vars.csv

```

```
const fetch = require('node-fetch');

class CustomApiProvider {
  constructor(options) {
    // The caller may override Provider ID (e.g. when using multiple instances of the same provider)
    this.providerId = options.id || 'custom provider';

    // The config object contains any options passed to the provider in the config file.
    this.config = options.config;
  }

  id() {
    return this.providerId;
  }

  async callApi(prompt) {
    // logic
}

module.exports = CustomApiProvider;
```

When in file node_modules\promptfoo\dist\src\esm.js I changed line `const resolvedPath = path.resolve(modulePath)` to `const resolvedPath = 'file://' + path.resolve(modulePath).replaceAll('\\', '/');`  then everything works correctly

On Linux this problem does not occur


Thanks for flagging. I believe this is addressed by
https://github.com/promptfoo/promptfoo/pull/652, which will be included in
a release published today. Hopefully that fixes it for you!

On Fri, Apr 12, 2024, 12:50 AM charles-m1 ***@***.***> wrote:

> OS: Windows 10
> node: 21.7.2
> promptfoo: 0.51.0
>
> When I try to use a custom provider (I think I have implemented it
> according to examples) then I get an error
>
> Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
>     at throwIfUnsupportedURLScheme (node:internal/modules/esm/load:239:11)
>     at defaultLoad (node:internal/modules/esm/load:130:3)
>     at ModuleLoader.load (node:internal/modules/esm/loader:403:13)
>     at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:56)
>     at new ModuleJob (node:internal/modules/esm/module_job:67:26)
>     at #createModuleJob (node:internal/modules/esm/loader:297:17)
>     at ModuleLoader.getJobFromResolveResult (node:internal/modules/esm/loader:254:34)
>     at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:235:17)
>     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
>     at async ModuleLoader.import (node:internal/modules/esm/loader:322:23) {
>   code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
> }
>
> promptfoo.config
>
> prompts: "{{question}}"
> providers: [customProvider.js]
> tests: vars.csv
>
>
> const fetch = require('node-fetch');
>
> class CustomApiProvider {
>   constructor(options) {
>     // The caller may override Provider ID (e.g. when using multiple instances of the same provider)
>     this.providerId = options.id || 'custom provider';
>
>     // The config object contains any options passed to the provider in the config file.
>     this.config = options.config;
>   }
>
>   id() {
>     return this.providerId;
>   }
>
>   async callApi(prompt) {
>     // logic
> }
>
> module.exports = CustomApiProvider;
>
> When in file node_modules\promptfoo\dist\src\esm.js I changed line const
> resolvedPath = path.resolve(modulePath) to const resolvedPath = 'file://' +
> path.resolve(modulePath).replaceAll('\', '/'); then everything works
> corectly
>
> On Linux this problem does not occur
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/promptfoo/promptfoo/issues/662>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACLYJWEY2KOR2O3ISRWFBLY46G5JAVCNFSM6AAAAABGDVABAOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGIZTSMZSGYYDIOI>
> .
> You are receiving this because you are subscribed to this thread.Message
> ID: ***@***.***>
>


Fix released in [0.52.0](https://github.com/promptfoo/promptfoo/releases/tag/0.52.0)