Skip to content

Re-running one of two parallel jobs restores the sibling's snapshot and loses its session #1778

Open

Description

@marcusrbrown

Since #1776, every job in a workflow run has its own scheduled/dispatch session key and cache save key. Restore still picks the newest whole-database snapshot under the shared ref prefix.

When two jobs that use the Action run in parallel in the same run, the job that saved first loses its session on a re-run. The newest snapshot is the sibling's, and the sibling's snapshot doesn't contain this job's session, so the re-run starts a fresh one.

These cases are not affected:

  • single-job workflows;
  • sequential needs: chains;
  • issue, PR and discussion sessions;
  • continuing a session across runs.

A possible fix is a save key of …-{runId}-{job}.{attempt} plus a first restore key of …-{runId}-{job}., so that a re-run restores its own job's latest snapshot before falling back as it does today. The . delimiter keeps fro-bot from prefix-matching fro-bot-remediate. A real merge of parallel histories is #1712.

Tests to add along with the fix:

  • two parallel saves followed by a re-run of the earlier job, checking that the session continues;
  • the cleanup and post paths producing the same cache key and artifact name with a matrix context, exercised through the real phase functions.

Activity

  1. fro-bot commented on Oct 10, 2026

    @fro-bot
    Owner

    Confirmed locally: parallel jobs save distinct snapshots, but re-running the earlier-saving job restores its sibling’s snapshot and loses session continuity. Its original cache entry still exists; restore selects the wrong one.

    Reproduction

    Used the real saveCache/restoreCache functions, isolated SQLite session fixtures, and an injected cache adapter modeling GitHub’s ordered, newest-prefix matching:

    1. Two runners begin with the same empty history.
    2. fro-bot saves its session; fro-bot-remediate independently saves its own session afterward.
    3. Re-run fro-bot with the same run ID and attempt 2.
    4. Restore reports a cache hit on …-38026680860-1-fro-bot-remediate; the requested fro-bot session is absent.

    This produced the expected continuity assertion failures for both schedule and workflow_dispatch. Re-running the later-saving sibling passed in both cases. The existing cache-key/invocation-identity suites also passed (21 tests). This was a local adapter-based reproduction, not a live parallel Actions run.

    Root cause

    • src/services/cache/cache-key.ts:64–71 distinguishes jobs when saving, but buildRestoreKeys at lines 36–43 has no run/job specificity.
    • src/services/cache/restore.ts:270–282 restores using a shared primary prefix plus broad fallbacks.
    • The logical session key remains stable across attempts, but its session is missing from the selected database; src/harness/phases/session-prep.ts:101–125 consequently finds no continuation.

    The existing re-run test checks identifier stability without restoring competing snapshots, so it misses this failure.

    Recommended next steps

    1. Adopt save keys shaped as {primary}-{runId}-{invocationIdentity}.{attempt}, including the matrix-leg identity, and prefer {primary}-{runId}-{invocationIdentity}. on restore.
    2. Make that preference the restore primary key, or perform a separate first lookup. @actions/cache prefix-matches its primary key before trying restore keys. Simply prepending a job-specific fallback behind today’s broad primary key still restores the sibling. A local selection control verified this ordering and the . delimiter’s protection against fro-bot matching fro-bot-remediate.
    3. Retain today’s broad primary/ref/repo fallbacks for new runs and old-format entries, and verify entity-bound session behavior remains intact. This is bounded re-run recovery; merging parallel histories remains Make concurrent Action session publication safe so Action runs need no repository lock #1712.
    4. Add regression coverage for earlier-job re-runs under both triggers, multiple attempts, prefix-related job names, matrix siblings, and legacy fallback. Exercise real runCleanup and runPost with matrix context, asserting the actual cache keys and artifact names agree at the external boundaries.

    Temporary reproduction tests were removed after investigation; the working tree is unchanged.


    Run Summary
    Field Value
    Event issues
    Repository fro-bot/agent
    Run ID 38088981712
    Cache hit
    Session ses_ed83630a6ffeseXBcwz3jYiRVf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions