{"record":{"id":"8163e2570d1e1752","repo":"tauri-apps/tauri","slug":"failed-with-exit-code","errorCode":null,"errorMessage":"{} `{}` failed with exit code {}","messagePattern":"(.+?) `(.+?)` failed with exit code (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri-cli/src/helpers/mod.rs","lineNumber":117,"sourceCode":"      .piped()\n      .map_err(|error| crate::error::Error::CommandFailed {\n        command: script.clone(),\n        error,\n      })?;\n    #[cfg(not(target_os = \"windows\"))]\n    let status = Command::new(\"sh\")\n      .arg(\"-c\")\n      .arg(&script)\n      .current_dir(cwd)\n      .envs(env)\n      .piped()\n      .map_err(|error| Error::CommandFailed {\n        command: script.clone(),\n        error,\n      })?;\n\n    if !status.success() {\n      crate::error::bail!(\n        \"{} `{}` failed with exit code {}\",\n        name,\n        script,\n        status.code().unwrap_or_default()\n      );\n    }\n  }\n\n  Ok(())\n}\n\n#[cfg(target_os = \"macos\")]\npub fn strip_semver_prerelease_tag(version: &mut semver::Version) -> crate::Result<()> {\n  use crate::error::Context;\n  if !version.pre.is_empty() {\n    if let Some((_prerelease_tag, number)) = version.pre.as_str().to_string().split_once('.') {\n      version.pre = semver::Prerelease::EMPTY;\n      version.build = semver::BuildMetadata::new(&format!(","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-cli/src/helpers/mod.rs#L99-L135","documentation":"`run_hook` executes config-defined hook scripts (such as `beforeBuildCommand`) via `sh -c` / `cmd /S /C` in the frontend directory (or the hook's configured `cwd`) with Tauri-provided env vars. If the script exits non-zero, the hook name, script text, and exit code are reported and the operation aborts.","triggerScenarios":"`tauri build` (or other phases calling `run_hook`) with a `beforeBuildCommand`/hook script that fails: missing dependencies, failing test/lint step embedded in the build script, or a script typo. Empty scripts are skipped, so only a non-empty failing script triggers this.","commonSituations":"CI where node_modules are absent and the build script imports a linter; scripts referencing binaries not on PATH in the hook's environment (`sh -c` non-login shell); frontend builds failing on out-of-memory or type errors.","solutions":["Run the exact script from the error message manually in the frontend dir and fix the failure it reports","Ensure the binaries the script calls (npx, pnpm, node) are on PATH for non-interactive shells","Install frontend dependencies before building (`npm ci`) if the script depends on local node_modules"],"exampleFix":"// before (tauri.conf.json) - script fails with exit code 1\n\"beforeBuildCommand\": \"npm run build && npm run test\"\n\n// after - keep the build hook minimal; run tests separately in CI\n\"beforeBuildCommand\": \"npm run build\"","handlingStrategy":"validation","validationCode":"# validate the hook script executes cleanly in a clean sh before building\nsh -c 'cd frontend && npm ci --silent && npm run build' || { echo 'hook script failed'; exit 1; }\ntauri build","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Test hook scripts with plain `sh -c '<script>'` from the frontend dir — the same way `run_hook` runs them","Ensure binaries used in hooks are on PATH for non-interactive shells","Keep build hooks minimal; move tests/lints to separate CI steps"],"tags":["tauri-cli","hooks","before-build-command","shell","config"],"backgroundTag":"command-exit-code-nonzero","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}