Skip to content

fix(release): correct declared type of parallel in PublishOptions - #36877

Open
arpitbharadwaj1 wants to merge 1 commit into
nrwl:masterfrom
arpitbharadwaj1:fix/publish-options-parallel-type
Open

fix(release): correct declared type of parallel in PublishOptions#36877
arpitbharadwaj1 wants to merge 1 commit into
nrwl:masterfrom
arpitbharadwaj1:fix/publish-options-parallel-type

Conversation

@arpitbharadwaj1

Copy link
Copy Markdown

Current Behavior

PublishOptions.parallel is typed as string (inherited from RunOptions.parallel in
shared-options.ts,
via PublishOptions = NxReleaseArgs & Partial<RunManyOptions> & {...} in
command-object.ts).

That type reflects the raw CLI/yargs value before normalization. On the CLI path, the raw string
is always passed through readParallelFromArgsAndEnv()
(shared-options.ts),
which coerces it to a real number before it reaches the task orchestrator.

However, callers using the programmatic API — e.g. the releasePublish function returned by
createAPI(...) in
publish.ts,
used directly instead of going through yargsReleaseCommand — never go through that normalization
step. If such a caller passes parallel as a numeric string (matching the declared TS type), it
flows straight into getThreadPoolSize()
(task-orchestrator.ts):

const discrete = options['parallel'];
const continuous = continuousCount;
const total = discrete + continuous; // string concatenation, not addition, if parallel is a string

getThreadPoolSize only coerces the sentinel values 'true'/'false'/''/undefined — any other
string (including a plain numeric string like "3") passes through unchanged. total then reaches:

process.stdout.setMaxListeners(total + defaultMaxListeners);
process.stderr.setMaxListeners(total + defaultMaxListeners);
process.setMaxListeners(total + defaultMaxListeners);

setMaxListeners(n) requires n to be a number and throws ERR_INVALID_ARG_TYPE when given a
string, so a type-correct programmatic caller crashes at runtime.

Expected Behavior

The declared type of parallel should match whatever a caller of the programmatic API is actually
required to provide — a real number, not a string.

Fix

PublishOptions.parallel is now typed as number, using Omit<Partial<RunManyOptions>, 'parallel'>
to override the inherited CLI-string type (a plain intersection would otherwise collapse to never).
This is a type-only change — no runtime behavior is modified.

Repro

const publish = createAPI(overrideReleaseConfig, ignoreNxJsonConfig);
await publish({ groups: [...], dryRun: false, parallel: '3' /* matches the old declared type */ });
// throws inside task-orchestrator.ts because "3" + continuousCount is string concatenation,
// and the resulting string is passed to process.stdout.setMaxListeners(...)

Passing parallel as an actual number (contradicting the old declared type) avoided the crash,
confirming the type declaration didn't match the runtime contract for this code path.

Closes #36777

… to `number`

`PublishOptions.parallel` was typed as `string` (inherited from `RunOptions.parallel`
via `Partial<RunManyOptions>`), reflecting the raw CLI/yargs value before
`readParallelFromArgsAndEnv()` normalizes it to a real number.

Programmatic callers of `releasePublish()` (via `createAPI()`) receive the same
`PublishOptions` type but never go through that CLI-only normalization. The value
flows straight into `getThreadPoolSize()` in task-orchestrator.ts, where `NxArgs.parallel`
is declared `number` and is used in `total = discrete + continuous` before being passed
to `process.stdout.setMaxListeners(total + ...)`, which throws `ERR_INVALID_ARG_TYPE`
when given a string.

A type-correct programmatic caller (passing a string, per the old declared type) crashed
at runtime; only passing a number (contradicting the declared type) worked.

This fixes the type declaration only, using `Omit<Partial<RunManyOptions>, 'parallel'>`
to override the inherited CLI-string type with the `number` type programmatic callers
actually need. No runtime behavior changes.

Closes nrwl#36777
@arpitbharadwaj1
arpitbharadwaj1 requested a review from a team as a code owner September 1, 2026 08:27
@netlify

netlify Bot commented Sep 1, 2026

Copy link
Copy Markdown

👷 Deploy request for nx-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 24c19fd

@netlify

netlify Bot commented Sep 1, 2026

Copy link
Copy Markdown

👷 Deploy request for nx-dev pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 24c19fd

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

releasePublish() programmatic API requires parallel to be a number, but PublishOptions types it as string

1 participant