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

  1. 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.
  2. 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.
  3. 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

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


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)