microsoft/typescript-go · error · Error

Prerelease version should be in the form of dev.<number>.<nu

Error message

Prerelease version should be in the form of dev.<number>.<number>, but got ${prerelease}

What it means

In runPackVsixExtensions, the release path requires a prerelease identifier of the exact form `dev.<number>.<number>` (regex `dev\.(\d+)\.(\d+)`) because VS Code has no real semver prerelease channel — the extension version is mechanically rewritten to `0.<number>.<number>` (VS Code then treats 0.x pre-releases correctly). Anything not matching (dev, dev.1, beta.1.0, 1.2.3) is rejected.

Source

Thrown at Herebyfile.mjs:2327

    if (!extensions.length) {
        console.log("No VSIX targets configured; skipping extension packaging.");
        return;
    }

    // We don't use vscode:prepublish, as that would run the build for each package below.
    await $({ cwd: extensionDir, env: releasePackageEnv })`npm run bundle:release`;

    let version = "0.0.0";
    if (options.forRelease) {
        // No real semver prerelease versioning.
        // https://code.visualstudio.com/api/working-with-extensions/publishing-extension#prerelease-extensions
        assert(options.setPrerelease, "forRelease is true but setPrerelease is not set");
        const prerelease = options.setPrerelease;
        assert(typeof prerelease === "string", "setPrerelease is not a string");
        // parse `dev.<number>.<number>`.
        const match = prerelease.match(/dev\.(\d+)\.(\d+)/);
        if (!match) {
            throw new Error(`Prerelease version should be in the form of dev.<number>.<number>, but got ${prerelease}`);
        }
        // Set version to `0.<number>.<number>`.
        version = `0.${match[1]}.${match[2]}`;
    }

    console.log("Version:", version);

    await Promise.all(extensions.map(async ({ npmDir, npmPackageName, nodeOs, vscodeTarget, sourceDir, extensionDir: thisExtensionDir, vsixPath, vsixManifestPath, vsixSignaturePath }) => {
        const npmLibDir = usePublishedPlatformPackagesForVsix
            ? await getPublishedPlatformPackageLibDir(npmPackageName)
            : path.join(npmDir, "lib");
        const extensionLibDir = path.join(thisExtensionDir, "lib");
        await fs.promises.mkdir(extensionLibDir, { recursive: true });

        await cpWithoutNodeModulesOrTsconfig(sourceDir, thisExtensionDir);
        await cpWithoutNodeModulesOrTsconfig(npmLibDir, extensionLibDir);
        await fs.promises.chmod(path.join(extensionLibDir, nativePreviewExeName(nodeOs)), 0o755);

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Pass the prerelease in the required form, e.g. `--setPrerelease=dev.1.0`
  2. Fix the CI/release script that assembles the value so it always emits `dev.<int>.<int>`
  3. Remember the two numbers map directly to the VSIX version's minor/patch (0.N.M) — choose them per the nightly counter you want

Example fix

# before
npx hereby native-preview:release --forRelease --setPrerelease=beta.1.0

# after
npx hereby native-preview:release --forRelease --setPrerelease=dev.1.0
Defensive patterns

Strategy: validation

Validate before calling

const m = prerelease.match(/^dev\.(\d+)\.(\d+)$/);
if (!m) {
  throw new Error(`setPrerelease must be dev.<int>.<int>, got "${prerelease}"`);
}
const vsixVersion = `0.${m[1]}.${m[2]}`;

Type guard

function isDevPrerelease(v: string): v is `dev.${number}.${number}` {
  return /^dev\.\d+\.\d+$/.test(v);
}

Prevention

When it happens

Trigger: Running `npx hereby native-preview:release --forRelease` (or the VSIX pack task) with a --setPrerelease value that doesn't match `dev.N.M`, e.g. `--setPrerelease=dev`, `--setPrerelease=dev.1`, or `--setPrerelease=beta.1.0`. Note the preceding asserts also require setPrerelease to be present and a string.

Common situations: CI templates the flag from a variable that produces a different format; a developer assumes semver prerelease syntax is allowed; the flag is simply forgotten (caught earlier by the assert).

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/34a81ea467157bec. Report an issue: GitHub.