vercel/turborepo · error · ConvertError
package_manager-unexpected
package_manager-unexpected
Error message
Not a bun project
What it means
The bun manager's read() re-runs detect() (bun.lockb/bun.lock exists, or package.json declares bun) and throws ConvertError type package_manager-unexpected when the workspace is not a bun project. In the standard flow read() executes only after detect() passed, so this error indicates direct invocation or that workspace state changed between the two calls.
Source
Thrown at packages/turbo-workspaces/src/managers/bun.ts:58
*/
// eslint-disable-next-line @typescript-eslint/require-await -- must match the detect type signature
async function detect(args: DetectArgs): Promise<boolean> {
const lockFile = path.join(args.workspaceRoot, PACKAGE_MANAGER_DETAILS.lock);
const packageManager = getWorkspacePackageManager({
workspaceRoot: args.workspaceRoot
});
return (
fs.existsSync(lockFile) || packageManager === PACKAGE_MANAGER_DETAILS.name
);
}
/**
Read workspace data from bun workspaces into generic format
*/
async function read(args: ReadArgs): Promise<Project> {
const isBun = await detect(args);
if (!isBun) {
throw new ConvertError("Not a bun project", {
type: "package_manager-unexpected"
});
}
const packageJson = getPackageJson(args);
const { name, description } = getWorkspaceInfo(args);
const workspaceGlobs = parseWorkspacePackages({
workspaces: packageJson.workspaces
});
return {
name,
description,
packageManager: PACKAGE_MANAGER_DETAILS.name,
paths: expandPaths({
root: args.workspaceRoot,
lockFile: PACKAGE_MANAGER_DETAILS.lock
}),
workspaceData: {View on GitHub (pinned to 9f94a7d215)
Solutions
- Use getWorkspaceDetails() so detection picks the right manager before read() runs
- Guard direct calls with MANAGERS.bun.detect({ workspaceRoot }) and skip on false
- If the project should be bun, restore bun.lock/bun.lockb or declare bun in package.json first
Example fix
// before
const project = await MANAGERS.bun.read({ workspaceRoot }); // no bun lockfile
// after
if (await MANAGERS.bun.detect({ workspaceRoot })) {
const project = await MANAGERS.bun.read({ workspaceRoot });
} else {
throw new Error(`Expected a bun workspace at ${workspaceRoot}`);
} Defensive patterns
Strategy: validation
Validate before calling
if (await MANAGERS.bun.detect({ workspaceRoot })) {
const project = await MANAGERS.bun.read({ workspaceRoot });
} else {
throw new Error(`Refusing bun read: ${workspaceRoot} has no bun lockfile or declaration`);
} Type guard
function isUnexpectedManagerError(e: unknown): boolean {
return e instanceof ConvertError && e.type === "package_manager-unexpected";
} Try / catch
try {
const project = await MANAGERS.bun.read({ workspaceRoot });
} catch (e) {
if (e instanceof ConvertError && e.type === "package_manager-unexpected") {
// workspace is not bun-managed; use getWorkspaceDetails() for generic detection
} else throw e;
} Prevention
- Run detect() before read() when using manager internals directly
- Use getWorkspaceDetails() for automatic manager selection
- In tests, ensure bun fixtures contain a bun.lockb/bun.lock or a bun packageManager field
When it happens
Trigger: Calling MANAGERS.bun.read({ workspaceRoot }) on a repo with no bun.lockb/bun.lock and no bun packageManager declaration; deleting the lockfile between detection and read.
Common situations: Direct API use in scripts or tests on non-bun fixtures; a stale Project/workspaceRoot captured before the user switched package managers.
Related errors
- package_manager-unable_to_detect
- package_manager-unexpected
- bun-workspace_glob_error
- error_removing_node_modules
- Unable to update README.md
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/12cceffe5a2bad3d.
Report an issue: GitHub.