denoland/deno · error

No means to authenticate. Pass a token to `--token`, or enab

Error message

No means to authenticate. Pass a token to `--token`, or enable tokenless publishing from GitHub Actions using OIDC. Learn more at https://deno.co/ghoidc

What it means

When publishing from GitHub Actions without --token, Deno attempts tokenless OIDC auth using the ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN env vars that Actions injects when the job has the id-token permission. This error means GITHUB_ACTIONS=true but both vars are absent — the workflow never granted OIDC — and no other credential was supplied.

Source

Thrown at cli/tools/publish/auth.rs:36

}

pub(crate) fn is_gha() -> bool {
  std::env::var("GITHUB_ACTIONS").unwrap_or_default() == "true"
}

pub(crate) fn gha_oidc_token() -> Option<String> {
  std::env::var("ACTIONS_ID_TOKEN_REQUEST_TOKEN")
    .ok()
    .filter(|s| !s.is_empty())
}

fn get_gh_oidc_env_vars() -> Option<Result<(String, String), AnyError>> {
  if std::env::var("GITHUB_ACTIONS").unwrap_or_default() == "true" {
    let url = std::env::var("ACTIONS_ID_TOKEN_REQUEST_URL");
    let token = std::env::var("ACTIONS_ID_TOKEN_REQUEST_TOKEN");
    match (url, token) {
      (Ok(url), Ok(token)) => Some(Ok((url, token))),
      (Err(_), Err(_)) => Some(Err(anyhow::anyhow!(
        "No means to authenticate. Pass a token to `--token`, or enable tokenless publishing from GitHub Actions using OIDC. Learn more at https://deno.co/ghoidc"
      ))),
      _ => None,
    }
  } else {
    None
  }
}

pub fn get_auth_method(
  maybe_token: Option<String>,
  dry_run: bool,
) -> Result<AuthMethod, AnyError> {
  if dry_run {
    // We don't authenticate in dry-run mode.
    return Ok(AuthMethod::Interactive);
  }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Add `permissions: id-token: write` (plus `contents: read`) to the publishing job so Actions provides the OIDC vars
  2. Or pass a credential explicitly: deno publish --token $DENO_TOKEN
  3. Verify the vars exist in the job: env | grep ACTIONS_ID_TOKEN
  4. If OIDC is blocked by policy, store a PAT as a secret and use --token

Example fix

# .github/workflows/publish.yml — before
jobs:
  publish:
    steps:
      - run: deno publish
# after
jobs:
  publish:
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: denoland/setup-deno@v2
      - run: deno publish
Defensive patterns

Strategy: validation

Validate before calling

# CI preflight: detect missing OIDC grant before publishing
if [ "${GITHUB_ACTIONS:-}" = "true" ] && [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then
  echo '::error::job needs permissions: id-token: write for tokenless publish'
  exit 1
fi
deno publish

Prevention

When it happens

Trigger: `deno publish` in a GitHub Actions workflow with no --token where the job is missing permissions: id-token: write, or where OIDC is disabled at the enterprise/organization level.

Common situations: Publish workflows copied without the permissions block; org policies restricting id-token; self-hosted or non-GitHub runners where the ACTIONS_ID_TOKEN_* vars are never set.

Understand the failure class

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/47e24cb27ac4201d. Report an issue: GitHub.