can1357/oh-my-pi · error · Error
packages/coding-agent/package.json has no valid version
Error message
packages/coding-agent/package.json has no valid version
What it means
prepareAgentBinaries reads `packages/coding-agent/package.json` to learn the agent version used for binary naming and caching, and throws this error when the parsed manifest has no non-empty string `version` field. It treats a missing/invalid version as fatal because binaries are cached under `omp-linux-<arch>-<version>` and cross natives are fetched at that version.
Source
Thrown at packages/metaharness/src/tb/agent.ts:56
for (const [entry, file] of await archive.files()) {
const name = path.posix.basename(entry);
if (!name.startsWith(`pi_natives.linux-${arch}`) || !name.endsWith(".node")) continue;
await Bun.write(path.join(NATIVES_DIR, name), file);
extracted++;
}
if (extracted === 0) throw new Error(`@oh-my-pi/${pkg}@${version} tarball contained no .node files`);
}
}
/** Build and cache self-contained omp binaries for the selected guest architectures. */
export async function prepareAgentBinaries(opts: {
arches: GuestArch[];
cacheDir: string;
rebuild: boolean;
}): Promise<AgentBinaries> {
const manifest = (await Bun.file(path.join(CODING_AGENT_DIR, "package.json")).json()) as { version?: unknown };
if (typeof manifest.version !== "string" || manifest.version.length === 0) {
throw new Error("packages/coding-agent/package.json has no valid version");
}
const arches = [...new Set(opts.arches)];
const cached: Partial<Record<GuestArch, string>> = {};
for (const arch of arches) {
cached[arch] = path.join(opts.cacheDir, `omp-linux-${arch}-${manifest.version}`);
}
const missing: GuestArch[] = [];
for (const arch of arches) {
if (opts.rebuild || !(await Bun.file(cached[arch]!).exists())) missing.push(arch);
}
if (missing.length > 0) {
await fs.mkdir(opts.cacheDir, { recursive: true });
await refreshCrossNatives(missing, manifest.version);
const targets = missing.map(arch => `linux-${arch}`).join(",");
await run(["bun", "scripts/ci-release-build-binaries.ts", "--targets", targets], REPO_ROOT);
for (const arch of missing) {View on GitHub (pinned to 9690622007)
Solutions
- Ensure `packages/coding-agent/package.json` contains a valid non-empty `"version"` string
- Verify CODING_AGENT_DIR points at the real packages/coding-agent directory
- Restore the file if corrupted: `git checkout -- packages/coding-agent/package.json`
- Validate the JSON parses (`bun -e 'await Bun.file(...).json()'`) if the file looks wrong
Example fix
// before
{ "name": "@oh-my-pi/coding-agent" } // no version → throws
// after
{ "name": "@oh-my-pi/coding-agent", "version": "1.2.3" } Defensive patterns
Strategy: type-guard
Validate before calling
const manifest = await Bun.file(path.join(CODING_AGENT_DIR, "package.json")).json();
if (typeof manifest.version !== "string" || manifest.version.length === 0) {
throw new Error("coding-agent package.json is missing a valid version");
} Type guard
function hasVersion(m: unknown): m is { version: string } {
return typeof m === "object" && m !== null &&
typeof (m as { version?: unknown }).version === "string" &&
(m as { version: string }).version.length > 0;
} Try / catch
let manifest: { version?: unknown };
try {
manifest = await Bun.file(path.join(CODING_AGENT_DIR, "package.json")).json();
} catch (err) {
throw new Error(`cannot read coding-agent package.json: ${err}`);
}
if (!hasVersion(manifest)) throw new Error("coding-agent package.json has no valid version"); Prevention
- Never hand-edit or strip the version field from package.json
- Verify CODING_AGENT_DIR points at the real package directory
- Restore the manifest from git if corrupted
- Validate package.json parses in CI before binary builds
When it happens
Trigger: Calling `prepareAgentBinaries` (or the `binaries` entrypoint) when the coding-agent package.json is missing its version, has `version: ""`, or the file is malformed/unparseable so `manifest.version` is undefined.
Common situations: Running from a workspace where the package was stripped or renamed; a generated/hand-edited package.json missing the version field; pointing CODING_AGENT_DIR at the wrong directory; corrupted checkout.
Related errors
- Failed to load tree-sitter language: {err}
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
- Destination option ${key} must be a boolean
- ${destination} returned an invalid upload URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/acaf42d10a7c6efe.
Report an issue: GitHub.