Skip to content

cache-memory: update_cache_memory (+ conclusion AIC cache) save fails "token has no writable scopes" — job lacks actions: write #46807

Description

@arabkin

Summary

When a workflow uses cache-memory together with threat detection, the generated update_cache_memory job (and the conclusion job's daily-AIC usage cache save) fails to write the GitHub Actions cache with:

Cache reservation failed: cache write denied: token has no writable scopes

The cache save steps are continue-on-error: true, so the run stays green — but the cache is never persisted, silently defeating cross-run cache-memory.

Root cause

pkg/workflow/cache.gobuildUpdateCacheMemoryJob assigns the job empty permissions:

permissions := NewPermissionsEmpty().RenderToYAML() // Default: no special permissions needed
if setupActionRef != "" && len(c.generateCheckoutActionsFolder(data)) > 0 {
    permissions = NewPermissionsContentsRead().RenderToYAML() // dev mode only
}

The comment "no special permissions needed" is incorrect: GitHub's cache-reservation backend requires a writable token scope. The generated job therefore gets permissions: {} (or at most contents: read), and the reservation is denied.

Key detail: the cache backend accepts only actions/contents write as a "writable scope". It does not accept issues/pull-requests write — our conclusion job carries issues: write + pull-requests: write (from safe-outputs) and its daily-AIC cache save still fails with the same "no writable scopes" error. So the fix must be actions: write specifically.

This is on main, not just a released version.

Impact

  • update_cache_memory: cross-run cache-memory never persists → the feature is effectively a no-op on affected repos.
  • conclusion: the daily-AIC usage cache save fails (artifact fallback per ADR-39266 partially mitigates, but the cache lineage never forms).
  • Repos with a read-only default GITHUB_TOKEN (Settings → Actions → Workflow permissions = read) are always affected; and because the job sets permissions: {} explicitly, even a read-write default token is overridden to zero — so it fails regardless of the org/repo default.

No configuration workaround

Per reference/permissions.md, the frontmatter permissions: block governs the agent job's read scopes (writes go through safe-outputs); it does not reach these compiler-generated infra jobs. So there is no frontmatter/recompile/upgrade way to grant the scope — the job's permissions are hardcoded in the compiler.

Proposed fix

Emit actions: write on the cache-save jobs:

  • update_cache_memory (buildUpdateCacheMemoryJob, pkg/workflow/cache.go)
  • the daily-AIC usage cache save in the conclusion job (pkg/workflow/notify_comment.go)

(actions: write is the scope GitHub documents for cache mutation; contents: write also works but is broader than needed.)

Environment

  • gh-aw: v0.81.6 (latest release at time of writing); root cause also present on main.
  • Affected regardless of actions/cache major version (reproduced on both v5.0.5 and v6.1.0).
  • Workflow config: tools.cache-memory: true, safe-outputs (threat detection enabled), permissions: read-all, repo default workflow token = read-only.

Searched existing issues/PRs for "cache", "writable scopes", "actions: write", "cache save permission" — found none tracking this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions