jackwener/OpenCLI · critical
Could not find package.json above ${startFile}
Error message
Could not find package.json above ${startFile} What it means
findPackageRoot() walks upward from startFile's directory looking for a package.json to identify the package root. If it reaches the filesystem root (parent === dir) without finding one, it throws this Error. The library relies on the package root to locate built assets such as the builtin CLIs directory.
Source
Thrown at src/package-paths.ts:16
import * as fs from 'node:fs';
import * as path from 'node:path';
export interface PackageJsonLike {
bin?: string | Record<string, string>;
main?: string;
}
export function findPackageRoot(startFile: string, fileExists: (candidate: string) => boolean = fs.existsSync): string {
let dir = path.dirname(startFile);
while (true) {
if (fileExists(path.join(dir, 'package.json'))) return dir;
const parent = path.dirname(dir);
if (parent === dir) {
throw new Error(`Could not find package.json above ${startFile}`);
}
dir = parent;
}
}
export function getBuiltEntryCandidates(
packageRoot: string,
readFile: (filePath: string) => string = (filePath) => fs.readFileSync(filePath, 'utf-8'),
): string[] {
const candidates: string[] = [];
try {
const pkg = JSON.parse(readFile(path.join(packageRoot, 'package.json'))) as PackageJsonLike;
if (typeof pkg.bin === 'string') {
candidates.push(path.join(packageRoot, pkg.bin));
} else if (pkg.bin && typeof pkg.bin === 'object' && typeof pkg.bin.opencli === 'string') {
candidates.push(path.join(packageRoot, pkg.bin.opencli));
}View on GitHub (pinned to 49907e53dc)
Solutions
- Ensure a package.json exists at the project root and in every ancestor directory between startFile and the root.
- If bundling/packaging, include package.json in the output alongside the entry file.
- Run the code from within the installed package directory rather than a copied-out script.
- In containers, keep package.json in the image next to the built sources.
Example fix
// before (docker prune step) RUN rm -rf /app/package.json // after RUN cp /app/package.json /dist/ # or simply keep it in place
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
function hasPackageJsonAbove(startFile) {
let dir = path.dirname(path.resolve(startFile));
while (true) {
if (fs.existsSync(path.join(dir, 'package.json'))) return true;
const parent = path.dirname(dir);
if (parent === dir) return false;
dir = parent;
}
}
// if (!hasPackageJsonAbove(__filename)) fail early with a clear deployment error Try / catch
let projectRoot;
try {
projectRoot = findPackageRoot(__filename);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Could not find package.json above')) {
projectRoot = process.env.APP_ROOT ?? process.cwd();
logger.warn(`No package.json found; assuming project root ${projectRoot}`);
} else {
throw e;
}
} Prevention
- Always ship package.json with your bundled/deployed code (check Docker COPY scope and bundler externals).
- Run the app from inside the installed package directory; don't copy entry files to scratch dirs.
- For packaged binaries (pkg/nexe) or exotic filesystems, configure the library's root explicitly if it offers one.
- Smoke-test in the deployment image — the error only appears at runtime in the target filesystem layout.
When it happens
Trigger: Calling findPackageRoot (directly or via PACKAGE_ROOT/packageRoot/projectRoot/BUILTIN_CLIS/defaultBuiltinClisDir) with a startFile path outside any package — e.g. inside /tmp, a bare system directory, a deployed bundle that strips package.json, or a deleted/moved project without package.json at any ancestor level.
Common situations: Running from a global install or standalone binary, container images built with `--no-package-json` pruning, monorepo code copied to a scratch dir, tests running with a tmp cwd outside the repo, or packaged apps (pkg/nexe) that virtualize the filesystem.
Related errors
- Verify command returned no metric for baseline
- File not found: ${path}
- File must be a readable text file: ${path}
- File could not be read: ${path}
- state.vscdb not found: ${db}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0fcf0f2f094481ec.
Report an issue: GitHub.