Skip to content

Commit 74daf27

Browse files
committed
fix: detect running under Rosetta on Apple Silicone and show an error message instead of crashing
1 parent ad95c77 commit 74daf27

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

src/cli/commands/OnPostInstallCommand.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import {CommandModule} from "yargs";
2-
import {defaultSkipDownload} from "../../config.js";
2+
import chalk from "chalk";
3+
import {defaultSkipDownload, documentationPageUrls} from "../../config.js";
34
import {getLlamaForOptions} from "../../bindings/getLlama.js";
45
import {setForceShowConsoleLogPrefix} from "../../state.js";
6+
import {isRunningUnderRosetta} from "../utils/isRunningUnderRosetta.js";
7+
import {getConsoleLogPrefix} from "../../utils/getConsoleLogPrefix.js";
58

69
type OnPostInstallCommand = null;
710

@@ -12,7 +15,26 @@ export const OnPostInstallCommand: CommandModule<object, OnPostInstallCommand> =
1215
if (defaultSkipDownload)
1316
return;
1417

15-
setForceShowConsoleLogPrefix(false);
18+
setForceShowConsoleLogPrefix(true);
19+
20+
if (await isRunningUnderRosetta()) {
21+
console.error(
22+
getConsoleLogPrefix(false, false),
23+
chalk.red(
24+
"llama.cpp is not supported on Rosetta on Apple Silicone Macs. " +
25+
"Ensure that you're using a native arm64 node.js installation.")
26+
);
27+
console.error(
28+
getConsoleLogPrefix(false, false),
29+
"process.platform: " + process.platform + ", process.arch: " + process.arch
30+
);
31+
console.error(
32+
getConsoleLogPrefix(false, false),
33+
"troubleshooting: " + documentationPageUrls.troubleshooting.RosettaIllegalHardwareInstruction
34+
);
35+
36+
process.exit(1);
37+
}
1638

1739
try {
1840
await getLlamaForOptions({
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import path from "path";
2+
import {fileURLToPath} from "url";
3+
import process from "process";
4+
import {getPlatform} from "../../bindings/utils/getPlatform.js";
5+
import {spawnCommand} from "../../utils/spawnCommand.js";
6+
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
8+
9+
export async function isRunningUnderRosetta() {
10+
const platform = getPlatform();
11+
12+
// // only check for rosetta on macOS when x64 is detected
13+
if (platform !== "mac" || process.arch !== "x64")
14+
return false;
15+
16+
try {
17+
const res = await spawnCommand("sysctl", ["-n", "sysctl.proc_translated"], __dirname, process.env, false);
18+
19+
return res.combinedStd.trim() === "1";
20+
} catch (err) {
21+
return false;
22+
}
23+
}

src/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ export const documentationPageUrls = {
117117
Build: documentationCliUrl + "/source/build",
118118
Clear: documentationCliUrl + "/source/clear"
119119
}
120+
},
121+
troubleshooting: {
122+
RosettaIllegalHardwareInstruction: documentationUrl + "/guide/troubleshooting#illegal-hardware-instruction"
120123
}
121124
} as const;
122125
export const recommendedBaseDockerImage = "node:20";

0 commit comments

Comments
 (0)