Yeachan-Heo/oh-my-codex · error · Error

[native-assets] package.json is missing version

Error message

[native-assets] package.json is missing version

What it means

getPackageVersion reads the package's package.json and throws when the version field is missing or whitespace-only. The native-assets machinery needs the version to compute asset paths/names, so an absent version is fatal.

Source

Thrown at src/cli/native-assets.ts:74

const NATIVE_MANIFEST_URL_ENV = 'OMX_NATIVE_MANIFEST_URL';
const NATIVE_RELEASE_BASE_URL_ENV = 'OMX_NATIVE_RELEASE_BASE_URL';
const NATIVE_CACHE_DIR_ENV = 'OMX_NATIVE_CACHE_DIR';
export const EXPLORE_BIN_ENV = 'OMX_EXPLORE_BIN';
export const SPARKSHELL_BIN_ENV = 'OMX_SPARKSHELL_BIN';
export const API_BIN_ENV = 'OMX_API_BIN';

function packageJsonPath(packageRoot = getPackageRoot()): string {
  return join(packageRoot, 'package.json');
}

async function readPackageJson(packageRoot = getPackageRoot()): Promise<{ version?: string; repository?: { url?: string } | string }> {
  const raw = await readFile(packageJsonPath(packageRoot), 'utf-8');
  return JSON.parse(raw) as { version?: string; repository?: { url?: string } | string };
}

export async function getPackageVersion(packageRoot = getPackageRoot()): Promise<string> {
  const pkg = await readPackageJson(packageRoot);
  if (!pkg.version?.trim()) throw new Error('[native-assets] package.json is missing version');
  return pkg.version.trim();
}

function repositoryHttpBase(repository: { url?: string } | string | undefined): string | undefined {
  const raw = typeof repository === 'string' ? repository : repository?.url;
  if (!raw?.trim()) return undefined;
  const trimmed = raw.trim().replace(/^git\+/, '').replace(/\.git$/, '');
  if (trimmed.startsWith('https://github.com/')) return trimmed;
  if (trimmed.startsWith('http://github.com/')) return trimmed.replace(/^http:/, 'https:');
  return undefined;
}

export async function resolveNativeReleaseBaseUrl(
  packageRoot = getPackageRoot(),
  version?: string,
  env: NodeJS.ProcessEnv = process.env,
): Promise<string> {
  const override = env[NATIVE_RELEASE_BASE_URL_ENV]?.trim();

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Add a valid semver version field to package.json (even 0.0.0 for private packages)
  2. Verify getPackageVersion is called with the correct packageRoot
  3. If version is injected at publish time, inject it before native asset resolution runs

Example fix

// before
{ "name": "pkg", "private": true }
// after
{ "name": "pkg", "version": "0.0.0", "private": true }
Defensive patterns

Strategy: type-guard

Validate before calling

const pkg = JSON.parse(await readFile('package.json', 'utf-8'));
if (!pkg.version?.trim()) failEarly('package.json needs a version');

Type guard

function hasVersion(pkg: { version?: string }): pkg is { version: string } {
  return typeof pkg.version === 'string' && pkg.version.trim().length > 0;
}

Prevention

When it happens

Trigger: A package.json without a version field, version: "", or version: " "; a build/packaging step that strips or placeholder-fies the version; calling getPackageVersion with a packageRoot pointing at a directory whose package.json lacks version.

Common situations: Private workspace packages where version was omitted; publish pipelines that inject version at a later stage; monorepo tooling generating package.json without version; wrong packageRoot resolution.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/fbe8459e6ec9f3b2. Report an issue: GitHub.