JuliusBrussee/caveman · error

go build failed for ${artifact}

Error message

go build failed for ${artifact}

What it means

Thrown by the release-binary build script when a `go build` invocation for a release artifact exits with a non-zero status (the child's own compiler output has already been printed to stderr via stdio: "inherit"). The wrapper adds the artifact name because the Go toolchain error alone does not say which GOOS/GOARCH cross-compile target failed.

Source

Thrown at scripts/build-release-binaries.mjs:71

  }
  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;
      if (result.status !== 0) throw new Error(`go build failed for ${artifact}`);
      artifacts.push(artifact);
    }
  }
  artifacts.sort();
  const checksums = artifacts.map((artifact) => {
    const digest = createHash("sha256").update(readFileSync(join(out, artifact))).digest("hex");
    return `${digest}  ${artifact}`;
  }).join("\n") + "\n";
  writeFileSync(join(out, "checksums.txt"), checksums, { mode: 0o600 });
  return artifacts;
}

if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  try {
    const options = parseArgs(process.argv.slice(2));
    if (options.list) process.stdout.write(`${releaseArtifactNames(options.targets).sort().join("\n")}\n`);
    else process.stdout.write(`built ${build(options).length} signed-release inputs in ${options.out}\n`);
  } catch (error) {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Read the go compiler output printed just above the error — it names the actual file/package and cause; fix that first.
  2. Reproduce manually with the same env: GOOS=<goos> GOARCH=<arch> CGO_ENABLED=0 go build -trimpath -o /tmp/test <packagePath> to iterate faster.
  3. If a dependency does not support the target, either drop that target via --target or replace/guard the dependency with build tags.
  4. Ensure a current Go toolchain is installed and `go mod download` succeeds (clean module cache with `go clean -modcache` if it is corrupt).

Example fix

# before: dep uses cgo-only APIs
GOOS=windows GOARCH=arm64 go build ./... # fails -> script throws "go build failed for mytool-windows-arm64.exe"

# after: guard the dep with build tags
//go:build !windows
import "github.com/some/cgo-only-lib"
Defensive patterns

Strategy: try-catch

Validate before calling

import { spawnSync } from "node:child_process";
const probe = spawnSync("go", ["version"], { stdio: "pipe" });
if (probe.status !== 0) throw new Error("Go toolchain unavailable — install Go first");

Try / catch

try {
  buildRelease({ targets: [["linux", "amd64"]] });
} catch (err) {
  if (/^go build failed for /.test(err.message)) {
    // artifact name in the message maps to GOOS/GOARCH; the real compiler
    // error was already streamed to stderr — surface it, do not retry blindly
    process.exitCode = 1;
  } else throw err;
}

Prevention

When it happens

Trigger: Running the release script where the Go toolchain fails for a specific target: compile errors in the package being built, unsupported GOOS/GOARCH combination for a dependency (e.g. a package using cgo or syscall APIs unavailable on that platform), missing Go toolchain, or a full/corrupt module cache. Note CGO_ENABLED=0 is forced in the env.

Common situations: Adding a dependency that does not cross-compile to windows/arm64 or plan9 etc.; stale go.sum after a dependency bump; Go not installed or an ancient Go version rejecting the go directive in go.mod; building from a clean CI container without a warmed module cache while GOPROXY is misconfigured.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/53b76b9b31cec75c. Report an issue: GitHub.