JuliusBrussee/caveman · error
unknown argument ${arg}
Error message
unknown argument ${arg} What it means
Thrown by the release-binary build script's argument parser when it encounters a CLI argument that is not --out, --target, or --list. The parser is intentionally exhaustive with no pass-through, so any unrecognized flag aborts before a potentially long Go cross-compile starts.
Source
Thrown at scripts/build-release-binaries.mjs:52
return targets.flatMap(([goos, arch]) =>
RELEASE_BINARIES.map(([name]) => releaseArtifactName(name, goos, arch)));
}
function parseArgs(argv) {
let out = resolve(root, "dist", "binaries");
const targets = [];
for (let index = 0; index < argv.length; index++) {
const arg = argv[index];
if (arg === "--out") out = resolve(argv[++index] ?? "");
else if (arg === "--target") {
const value = argv[++index] ?? "";
const [goos, arch] = value.split("/");
if (!RELEASE_TARGETS.some(([knownOS, knownArch]) => knownOS === goos && knownArch === arch)) {
throw new Error(`unsupported release target ${JSON.stringify(value)}`);
}
targets.push([goos, arch]);
} else if (arg === "--list") return { out, targets: RELEASE_TARGETS, list: true };
else throw new Error(`unknown argument ${arg}`);
}
return { out, targets: targets.length ? targets : RELEASE_TARGETS, list: false };
}
function build({ out, targets }) {
mkdirSync(out, { recursive: true });
const artifacts = [];
for (const [goos, arch] of targets) {
for (const [name, packagePath] of RELEASE_BINARIES) {
const artifact = releaseArtifactName(name, goos, arch);
const output = join(out, artifact);
process.stderr.write(`build ${artifact}\n`);
const result = spawnSync("go", ["build", "-trimpath", "-o", output, packagePath], {
cwd: root,
env: { ...process.env, CGO_ENABLED: "0", GOOS: goos, GOARCH: arch },
stdio: "inherit",
});
if (result.error) throw result.error;View on GitHub (pinned to 27d5a3981a)
Solutions
- Remove the unrecognized flag — the script supports only --out <dir>, --target <goos/goarch> (repeatable), and --list.
- Run the script with no arguments or --list to see the usage implied by the supported flags and defaults.
- Check for shell expansion: quote arguments and ensure no stray tokens (e.g. an unquoted *) are appended.
Example fix
# before node scripts/build-release-binaries.mjs --verbose --target linux/amd64 # after node scripts/build-release-binaries.mjs --target linux/amd64
Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = new Set(["--out", "--target", "--list"]);
for (const a of argv) {
const flag = a.startsWith("-") ? a : null;
if (flag && !ALLOWED.has(flag) && !ALLOWED.has(flag.split("=")[0])) {
throw new Error(`unsupported flag ${flag}; allowed: ${[...ALLOWED].join(" ")}`);
}
} Prevention
- Wrap release invocations in a make/just recipe so humans never hand-type the flags.
- Quote all arguments in CI scripts to prevent shell expansion adding tokens.
When it happens
Trigger: Running scripts/build-release-binaries.mjs with a flag like --jobs 4, --verbose, -t linux/amd64, or a positional argument; or passing a flag that belongs to a different script (e.g. --os instead of --target).
Common situations: Copy-pasting a command from docs of a different version of the script; muscle-memory flags from goreleaser or similar tools; a trailing typo or unquoted shell glob expanding into extra args.
Related errors
- unsupported release target ${JSON.stringify(value)}
- cave_build_lock_missing: approve required evals, then run np
- cave_stale_lock:${checked.stale.join(",")}: run npm run buil
- caveman build: config must use strict lock and required sand
- cave_harness_request_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/6c2bce262c2cf45a.
Report an issue: GitHub.