Skip to content

Background actions frequently fail on Windows due to locking event.json #4641

Open

Description

@j3parker

Describe the bug

Every action step writes the event.json file before executing, which causes action-based background steps to frequently fail on Windows due to file-locking.

To Reproduce

In this repository I made a simple reusable action at the top of the repo:

runs:
  using: 'composite'
  steps:
    - run: echo hello
      shell: bash

I then added a workflow to execute that a bunch on Linux and Windows:

on: push

jobs:
  job:
    runs-on:  ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        counter: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    steps:
      - parallel:
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/
        - uses: $/

Expected behavior

The Linux ones always pass, unsurprisingly. This is the expected behaviour.

Runner Version and Platform

2.336.0 on windows-latest (and self-hosted Windows, with the same runner version)

What's not working?

On Windows, steps frequently fail with this error:

Error: The process cannot access the file 'D:\a_temp_github_workflow\event.json' because it is being used by another process.

I think this is likely due to this bit of code in the runner which writes event.json for every action. See ActionRunner.RunAsync() in the stack trace below.

Job Log Output

From https://github.com/j3parker/github-actions-parallel-tests/actions/runs/32063332105

With debugging enabled:

##[debug]Evaluating condition for step: 'Run j3parker/github-actions-parallel-tests@7c5d69fbd5a4044bbb0ec5b455cdd283177dd7d6'
##[debug]Evaluating: success()
##[debug]Evaluating success:
##[debug]=> true
##[debug]Result: true
##[debug]Loading inputs
##[debug]Loading env
Run j3parker/github-actions-parallel-tests@7c5d69fbd5a4044bbb0ec5b455cdd283177dd7d6
##[debug]Set step '' display name to: 'Run echo hello'
Run echo hello
0s
  ##[debug]Evaluating condition for step: 'Run echo hello'
  ##[debug]Evaluating: success()
  ##[debug]Evaluating success:
  ##[debug]=> true
  ##[debug]Result: true
  ##[debug]Starting: Run echo hello
  Error: The process cannot access the file 'D:\a\_temp\_github_workflow\event.json' because it is being used by another process.
  ##[debug]System.IO.IOException: The process cannot access the file 'D:\a\_temp\_github_workflow\event.json' because it is being used by another process.
  ##[debug]   at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
  ##[debug]   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
  ##[debug]   at System.IO.File.OpenHandle(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
  ##[debug]   at System.IO.File.WriteToFile(String path, FileMode mode, String contents, Encoding encoding)
  ##[debug]   at GitHub.Runner.Worker.ExecutionContext.WriteWebhookPayload()
  ##[debug]   at GitHub.Runner.Worker.ActionRunner.RunAsync()
  ##[debug]   at GitHub.Runner.Worker.Handlers.CompositeActionHandler.RunStepAsync(IStep step)
  ##[debug]Finished: Run echo hello

Activity

  1. MarshallOfSound commented on Aug 22, 2026

    @MarshallOfSound

    Same root cause, different symptom on macOS/Linux. No mandatory locking there so the runner's File.WriteAllText in WriteWebhookPayload() never throws — it truncates event.json to 0 bytes and rewrites it at the start of every step (including every inner step of a composite action), and any sibling background step whose process is reading $GITHUB_EVENT_PATH in that window gets an empty/partial file.

    Anything that bundles @actions/github is exposed because new Context() does JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH)) at module load. e.g. actions/download-artifact in a parallel: group next to a composite action:

    06:43:17.4583  ##[group]Run actions/download-artifact@3e5f45b…          <- parallel step B starts (node boots)
    06:43:17.7116  ##[start-action id=__parallel_0_0.yarn-cache-dir-path]   <- parallel step A (composite) starts its first inner step -> WriteWebhookPayload()
    06:43:17.7123  SyntaxError: Unexpected end of JSON input
                       at JSON.parse (<anonymous>)
                       at new Context (…/actions/download-artifact/3e5f45b…/dist/index.js:122275:37)
                       at …/dist/index.js:126301:23
                       at ModuleJob.run (node:internal/modules/esm/module_job:439:25)
    

    (https://github.com/electron/electron/actions/runs/32556056497/job/96994325756, runner 2.336.0, macos-15. We've hit this roughly daily across macOS and Windows hosted runners since adopting parallel: last week. It isn't a rare overlap: a node action reaches new Context() ~250ms after its step starts, which is about how long a sibling composite takes to start its first inner step, so the read and the truncate line up almost every time and it's just a question of who wins by a millisecond.)

    github.event comes from the job message and nothing in the worker ever mutates it, so there's no reason to re-serialize and rewrite it per step in the first place. Opened #4643 to write it once per job (and atomically if it ever has to be rewritten because a step removed it), which covers both the sharing violation here and the truncated read above.

  2. kjanat commented on Sep 6, 2026

    @kjanat
  3. j3parker commented on Sep 15, 2026

    @j3parker
    Author

    @TingluoHuang any chance this could be looked at? It kind of makes parallel unusable at scale (degree of parallelism and workflow frequency). @MarshallOfSound has a suggested fix which is pretty straight-forward and conservative.

  4. acidoxee commented on Oct 1, 2026

    @acidoxee

    Another data point on Linux, same as described by @MarshallOfSound above (truncated event.json → Unexpected end of JSON input).

    • Runner 2.337.0, GitHub-hosted larger runners (ubuntu-24.04, 4 cores)
    • Reader: actions/github-script@v9, failing at module load before the script runs:
      SyntaxError: Unexpected end of JSON input
          at JSON.parse (<anonymous>)
          at new Context (/home/runner/work/_actions/actions/github-script/v9/dist/index.js:60521:37)
      
    • Siblings in the same parallel: group: a run: step and a composite action whose own inner steps include actions/github-script
    • 30+ failed jobs in ~10 days on a single measured workflow (but there are others). And that's only counting runs that were still failed after any re-run, most of the time a retry passes. The step that fails is always the one starting at the same moment as the composite sibling
    • Downstream symptom: the step's output is then empty, so a later fromJSON(steps.<id>.outputs.result) fails with The template is not valid. … Error reading JToken from JsonReader. Path '', line 0, position 0.

    Our "workaround" for now would be to move any action using @actions/github out of parallel: groups, but that defeats the purpose. It would be great to get one of the PRs reviewed.

  5. jkroepke commented on Oct 18, 2026

    @jkroepke
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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions