Skip to content

ignoreManifest option in loadOptions not respected by execute() #1533

@jgornick

Description

@jgornick

Describe the bug

When using the execute() function in development mode with the ignoreManifest option set to true, the option is not properly passed through to the config loader, resulting in commands still being loaded from the manifest file (oclif.manifest.json) instead of from the filesystem. Additionally, when only ignoreManifest: true is provided without other options, it causes a TypeError due to missing required options that should be inferred automatically.

To Reproduce

  1. Create a basic oclif CLI with a development entry point (dev.js):
#!/usr/bin/env node
import { execute } from '@oclif/core'

await execute({
  development: true,
  dir: import.meta.url,
  loadOptions: {
    ignoreManifest: true,
  }
})
  1. Modify a command's description in the source file (e.g., add extra characters to make it visually different from the manifest)
  2. Run the command: dev.js your-command --help
  3. Observe the error:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
    at dirname (node:path:1457:5)
    at up (/node_modules/@oclif/core/lib/util/find-root.js:13:36)
    ...
  1. To work around the first issue, add root option:
await execute({
  development: true,
  dir: import.meta.url,
  loadOptions: {
    ignoreManifest: true,
    root: import.meta.dirname
  }
})
  1. Run the command again: dev.js your-command --help
  2. Note that the command description matches the manifest file, not the source file (the ignoreManifest option is not being respected)

Expected behavior

  1. When ignoreManifest: true is provided in loadOptions, it should be passed through to the config loader and commands should be loaded from the filesystem
  2. Default options (like root and pjson) should be automatically inferred when ignoreManifest is provided, similar to how they're inferred when not using loadOptions
  3. The command help should display the description from the source file, not from the cached manifest

Or, an alternate expected behavior would be when development: true, it ignores the manifest so that it is always loading directly from source.

Screenshots

Debug output showing the issue:

With ignoreManifest: true only:

this.options {
  "ignoreManifest": true
}
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined

With both ignoreManifest: true and root:

this.options {
  "ignoreManifest": true,
  "root": "/path/to/bin"
}
ignoreManifest false  ← Still shows false despite being set to true

The ignoreManifest is logged before this line: config/plugin.ts

Environment (please complete the following information):

  • OS & version: macOS Sequoia 15.2
  • Shell/terminal & version: zsh 5.9
  • Node.js version: v22.21.1
  • @oclif/core version: 4.8.0

Additional context

The issue appears to be in how execute() handles the loadOptions parameter. It seems like:

  1. When loadOptions is provided, default options that would normally be inferred are not merged in
  2. The ignoreManifest option from loadOptions is not being passed down to the appropriate Config initialization

This makes it difficult to use development mode with changes to command files not reflected without rebuilding the manifest.

Workaround

Currently, there's no clean workaround. Even with explicitly providing root, the ignoreManifest flag doesn't get passed through, so developers must delete the oclif.manifest.json file manually during development to ensure commands load from source files.

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