Skip to content

Custom commands fail to load on Node.js 24.20.0 with "Invalid URL" #169

Closed

Description

@diego-sepulveda-lavin

Package version

14.1.0

Describe the bug

Description

On Node.js 24.20.0, Ace fails when it tries to discover custom commands from the application's commands directory.

A fresh AdonisJS application works until the first custom command is created.

Steps to reproduce

  1. Create a fresh AdonisJS application using Node.js 24.20.0.
  2. Confirm that the command list works:
node ace list
  1. Create a custom command:
node ace make:command greet
  1. Run the command list again:
node ace list

Actual behavior

Ace fails with:

RuntimeException: Invalid command exported from "greet.js" file. Invalid URL

The generated command is valid. The error occurs while Ace validates its metadata.

Expected behavior

Ace should load the custom command and display it in the command list.

Regression

The same application and custom command work correctly with Node.js 24.19.0. The problem appears after upgrading to Node.js 24.20.0.

Additional context

The stack trace points to validateCommandMetaData in @adonisjs/ace.

Ace uses jsonschema@1.5.0 to validate command metadata. That package resolves references using the following URL base:

new URL(switchSchema, 'thismessage::/')

Node.js 24.20.0 rejects this base URL with ERR_INVALID_URL, whereas Node.js 24.19.0 accepts it.

Environment

  • @adonisjs/ace: 14.1.0
  • @adonisjs/core: 7.5.0
  • Node.js: 24.20.0
  • pnpm: 11.24.0
  • OS: macOS

Reproduction repo

No response

Activity

  1. mateocerri commented on Aug 28, 2026

    @mateocerri

    Just ran into this exact same problem while debugging my commands inside a Docker environment on a server, so seeing this issue opened was very timely. I tested and reproduced the exact same failure across Amazon Linux and Windows specifically after updating to Node.js v24.20.0 (everything was running fine on v24.11.1 / v24.19.0).

    Spent some time tracing through the execution inside validateCommandMetaData and jsonschema to find why Ace was throwing Invalid URL on completely valid commands. Here's the step-by-step diagnostic:


    Root Cause Breakdown

    1. Missing base / schema ID:
      Ace defines its command validation schema using Draft-07 conventions without an explicit id (Draft-04) or $id (Draft-07) at the root level, and no options.base is provided when calling new Validator().validate(command, schema).

    2. Pointer resolution in jsonschema:
      Because Ace's schema starts with $ref: "#/definitions/CommandMetaData", jsonschema delegates to Validator.prototype.resolve() (node_modules/jsonschema/lib/validator.js:263).
      When ctx.resolve() computes the relative reference against the empty base, it concatenates schema.id (undefined) with the fragment pointer, yielding an absolute path with a leading slash:
      '/undefined#/definitions/CommandMetaData'.

    3. Node 24.20.0 strict URL parser:
      jsonschema then evaluates:

      let parsed = new URL(switchSchema, 'thismessage::/');

      In Node <= 24.19.0, the parser tolerantly allowed absolute paths (starting with /) against non-hierarchical/opaque dummy schemes like thismessage::/.

      Starting in Node 24.20.0, the ada URL parser was updated to version 4.0.0 (7b1898a341) which strictly follows the WHATWG URL Standard. It now correctly rejects absolute paths on schemes without a host, immediately throwing TypeError [ERR_INVALID_URL]: Invalid URL.


    Minimal Reproduction in Node 24.20.0

    # Throws TypeError [ERR_INVALID_URL] in Node 24.20.0:
    node -e "new URL('/undefined#/definitions/CommandMetaData', 'thismessage::/')"
    
    # Passes if the base URI is hierarchical:
    node -e "console.log(new URL('/undefined#/definitions/CommandMetaData', 'http://localhost/').href)"

    Potential Fixes in Ace

    • Provide an explicit schema $id / base when invoking new Validator().validate(...), or validate definitions.CommandMetaData directly to avoid the root-level $ref URL resolution.
    • Alternatively, migrate the metadata validation to VineJS or a modern schema validator to remove the legacy jsonschema dependency entirely.

    Temporary workaround for anyone blocked: patch 'thismessage::/' to 'http://localhost/' in node_modules/jsonschema/lib/validator.js via patch-package, or pin your environment to node:24.19 / Node <= 24.19.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions