cross-rs/cross · error
expected GHA envfile to exist
Error message
expected GHA envfile to exist
What it means
write_to_gha_env_file appends a line to a GitHub Actions environment file identified by an env var (e.g. GITHUB_OUTPUT). If that env var is not set, the function tolerates running outside GitHub Actions — but only when GITHUB_ACTIONS is also unset (local run). If the env var is missing while GITHUB_ACTIONS IS set (we are on a runner), it bails: a runner must always provide these files, so their absence is an error.
Solutions
- Ensure the step runs directly on the runner (not in a nested container/sanitized env) so GitHub sets and exposes GITHUB_OUTPUT; or explicitly forward -e GITHUB_OUTPUT=... when invoking docker.
- If the intent is a local run, unset/skip the GITHUB_ACTIONS variable (or pass a flag) so the function's local no-op path is taken instead of erroring.
- Export GITHUB_OUTPUT to a writable file path in the job before invoking xtask if using a custom runner image.
Example fix
// before (workflow) - run: docker run myimage xtask ci # GITHUB_OUTPUT not forwarded // after - run: docker run -e GITHUB_OUTPUT -e GITHUB_ACTIONS myimage xtask ci
Defensive patterns
Strategy: try-catch
Validate before calling
if std::env::var("GITHUB_ACTIONS").is_ok() {
std::env::var("GITHUB_OUTPUT").expect("GITHUB_OUTPUT must be set on a GHA runner");
} Try / catch
match gha_output("tag", &value) {
Ok(()) => {},
Err(e) if e.to_string().contains("expected GHA envfile") => {
eprintln!("not writing GHA output: environment file missing");
}
Err(e) => return Err(e),
} Prevention
- Run xtask CI steps directly on the runner, not inside nested containers without forwarded GITHUB_* vars.
- When using docker in workflows, pass -e GITHUB_OUTPUT -e GITHUB_ACTIONS explicitly.
- On self-hosted runners, verify the runner image provides the standard environment files.
When it happens
Trigger: Running gha_output (the only caller) inside a GitHub Actions runner where the GITHUB_OUTPUT environment variable is not present — e.g. running the xtask step in a container/job where GitHub's runner environment file setup did not happen, running via a wrapper that scrubs the env, or a custom runner image missing GITHUB_OUTPUT.
Common situations: A workflow step runs the xtask command inside `docker run`/a container action that does not forward GITHUB_OUTPUT and other GITHUB_* variables; a self-hosted runner with a stripped environment; using `env -i` or a sanitized exec context within an Actions job.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- output ` ` contains newlines, consider serializing with…
- Refusing to push without tag or branch. Specify a…
- CROSS_RUNNER environment variable name is reserved and…
- Could not get UserName.
- no valid choice to pick for image name
AI-assisted analysis of cross-rs/cross@8c1a8aa4b6 (2026-09-13).
Data as JSON: /api/errors/6411a11dceb01065.
Report an issue: GitHub.
Appendix: source
Thrown at xtask/src/util.rs:363
}
pub fn write_to_string(path: &Path, contents: &str) -> cross::Result<()> {
let mut file = fs::OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path)?;
writeln!(file, "{}", contents)?;
Ok(())
}
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files
pub fn write_to_gha_env_file(env_name: &str, contents: &str) -> cross::Result<()> {
eprintln!("{contents}");
let path = if let Ok(path) = env::var(env_name) {
PathBuf::from(path)
} else {
eyre::ensure!(
env::var("GITHUB_ACTIONS").is_err(),
"expected GHA envfile to exist"
);
return Ok(());
};
let mut file = fs::OpenOptions::new().append(true).open(path)?;
writeln!(file, "{}", contents)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use cross::shell::Verbosity;
use std::collections::BTreeMap;
#[test]View on GitHub (pinned to 8c1a8aa4b6)