Skip to content

Panic using gh workflow run in GitHub Actions #10519

Description

@catsby

Describe the bug

I was trying to use gh workflow run at the end of a step in a GitHub action to trigger another workflow run. After reading some documentation though it seems I'm doing things wrong and should be using reusable workflows instead, so I'll figure that out elsewhere...

Anyway, when trying to do this in a GitHub Action, the gh workflow run call always ended in a panic. Here's the step in the job:

      - name: Trigger Release Workflow
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh workflow run release.yml -f tag_name="${TAG}"

(the $TAG is correctly set in a previous job step)

Note the use of secrets.GITHUB_TOKEN, which might be part of the problem due to how that token is limited in GHA to prevent recursive actions, etc... but maybe not...

Here's the panic:

2025-02-28T14:35:15.4937350Z ##[group]Run printf '%s\n' "${TAG}"
2025-02-28T14:35:15.4937658Z �[36;1mprintf '%s\n' "${TAG}"�[0m
2025-02-28T14:35:15.4937964Z �[36;1mgh workflow run release.yml -f tag_name="${TAG}"�[0m
2025-02-28T14:35:15.4983044Z shell: /usr/bin/bash -e {0}
2025-02-28T14:35:15.4983277Z env:
2025-02-28T14:35:15.4983452Z   TAG: v0.1.0-nightly
2025-02-28T14:35:15.4983829Z   GITHUB_TOKEN: ***
2025-02-28T14:35:15.4984034Z ##[endgroup]
2025-02-28T14:35:15.5049366Z v0.1.0-nightly
2025-02-28T14:35:15.9590013Z panic: runtime error: invalid memory address or nil pointer dereference
2025-02-28T14:35:15.9591635Z [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x13eed8a]
2025-02-28T14:35:15.9592318Z 
2025-02-28T14:35:15.9596306Z goroutine 1 [running]:
2025-02-28T14:35:15.9598926Z github.com/cli/cli/v2/pkg/cmd/workflow/shared.FindWorkflow(0xc000abd8f0, {0x22c13c0, 0xc0002e48d0}, {0x7ffecc3d2c67, 0xb}, {0xc000abd8e0, 0x1, 0x1})
2025-02-28T14:35:15.9600986Z 	/home/runner/work/cli/cli/pkg/cmd/workflow/shared/shared.go:139 +0x1aa
2025-02-28T14:35:15.9604432Z github.com/cli/cli/v2/pkg/cmd/workflow/shared.ResolveWorkflow({0x7fd132b6afc8, 0xc000724b40}, 0xc0003b4790, 0xc00061f9a0?, {0x22c13c0?, 0xc0002e48d0?}, 0x0?, {0x7ffecc3d2c67, 0xb}, {0xc000abd8e0, ...})
2025-02-28T14:35:15.9606415Z 	/home/runner/work/cli/cli/pkg/cmd/workflow/shared/shared.go:207 +0x2b5
2025-02-28T14:35:15.9607292Z github.com/cli/cli/v2/pkg/cmd/workflow/run.runRun(0xc00084b180)
2025-02-28T14:35:15.9608084Z 	/home/runner/work/cli/cli/pkg/cmd/workflow/run/run.go:273 +0x251
2025-02-28T14:35:15.9609089Z github.com/cli/cli/v2/pkg/cmd/workflow/run.NewCmdRun.func2(0xc000856008?, {0xc0002b6f30?, 0x4?, 0x178a487?})
2025-02-28T14:35:15.9610121Z 	/home/runner/work/cli/cli/pkg/cmd/workflow/run/run.go:128 +0x311
2025-02-28T14:35:15.9610972Z github.com/spf13/cobra.(*Command).execute(0xc000856008, {0xc0002b6f00, 0x3, 0x3})
2025-02-28T14:35:15.9611919Z 	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:985 +0xaaa
2025-02-28T14:35:15.9612678Z github.com/spf13/cobra.(*Command).ExecuteC(0xc0006d6008)
2025-02-28T14:35:15.9613440Z 	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:1117 +0x3ff
2025-02-28T14:35:15.9614179Z github.com/spf13/cobra.(*Command).ExecuteContextC(...)
2025-02-28T14:35:15.9615150Z 	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:1050
2025-02-28T14:35:15.9615811Z github.com/cli/cli/v2/internal/ghcmd.Main()
2025-02-28T14:35:15.9616459Z 	/home/runner/work/cli/cli/internal/ghcmd/cmd.go:119 +0x53b
2025-02-28T14:35:15.9617003Z main.main()
2025-02-28T14:35:15.9619832Z 	/home/runner/work/cli/cli/cmd/gh/main.go:10 +0x13
2025-02-28T14:35:15.9629795Z ##[error]Process completed with exit code 2.

I believe the panic comes from the cli/cli/pkg/cmd/workflow/shared/shared.go:139 in the stack there.

if _, err := strconv.Atoi(workflowSelector); err == nil || isWorkflowFile(workflowSelector) {
workflow, err := getWorkflowByID(client, repo, workflowSelector)
if err != nil {
var httpErr api.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode == 404 {
return nil, fmt.Errorf("workflow %s not found on the default branch", workflowSelector)
}
}
return []Workflow{*workflow}, nil
}

On line 135 we check for errors.As() && httpErr.StatusCode == 404 in order to return an err, so I'm speculating that the getWorkflowByID() call on 132 is returning a nil workflow with some other error code that's not a http error or not a 404, and as a result we get the nil pointer dereference on 139.

I was going to add a PR to return a generic error message between line 137 and 138, but the contributing guide asks (suggests?) to not open PRs unless there's a help-wanted on a bug or something, plus in the short time I looked I wasn't sure how to write a test for this so I just opt to give all this info here.

Again just speculation but maybe something to do with the token I'm using, because using gh workflow run on my machine while authenticated works fine:

 ➜ gh workflow run release.yml -f tag_name="v0.1.0-nightly"
✓ Created workflow_dispatch event for release.yml at main

To see runs for this workflow, try: gh run list --workflow=release.yml

So maybe the getWorkflowByID() call is returning a 403 or something due to the token being used?

Affected version

This is happening inside GitHub Actions, so I'm not totaly sure what gh version, but here's the runner version:

2025-02-28T14:34:58.2988493Z Current runner version: '2.322.0'
2025-02-28T14:34:58.3029586Z ##[group]Operating System
2025-02-28T14:34:58.3031098Z Ubuntu
2025-02-28T14:34:58.3032312Z 24.04.2
2025-02-28T14:34:58.3033375Z LTS
2025-02-28T14:34:58.3034492Z ##[endgroup]
2025-02-28T14:34:58.3035920Z ##[group]Runner Image
2025-02-28T14:34:58.3037214Z Image: ubuntu-24.04
2025-02-28T14:34:58.3038421Z Version: 20250223.1.0

Steps to reproduce the behavior

  1. Add a workflow (a) that does something and can be dispatched from another workflow (b)
  2. In workflow (b) add the step above that uses gh workflow run
  3. Run workflow (b)
  4. Panic?

Expected vs actual behavior

Return an error instead of panic, to help educate me on what I'm doing wrong.

I'm happy to PR a fix here as I suspect even if my speculations on tokens are wrong, we probably still want to return nil, err between 137 and 138. Tips on how/where to test for that would be cool too, if we want to have a regression test there.

Activity

  1. added
    priority-2Affects more than a few users but doesn't prevent core functions
    gh-workflowrelating to the gh workflow command
    on Feb 28, 2025
  2. williammartin commented on Feb 28, 2025

    @williammartin
    Member

    Hey @catsby,

    Thanks for the great bug report.

    I'm not sure about the token permissions issue (we can look into that if you like) but you're totally right in your debugging of the panic. It was introduced in this PR: #10328

    Gonna hand this off to @jtmcg since it's the end of my day.

  3. catsby commented on Feb 28, 2025

    @catsby
    Author

    Thanks @williammartin! For the token permissions thing, it would be neat to know if my suspicion is correct but I'm not going to request someone go digging just to satisfy my curiosity :P

    I'll still open to sending a PR but again the contributing guide suggests I hold off for now, and aside from any tests it's likely just a 1-line change anyway so I'm indifferent if a maintainer just goes ahead and fixes it.

    Have a great weekend 👋

  4. iamazeem commented on Feb 28, 2025

    @iamazeem
    Contributor

    Hey @catsby,

    Tried to reproduce this.
    Working fine for me.
    Got 404 and 403 but no panic.

    Could you please see what I'm missing?

    Here are the workflows that I used:

    .github/workflows/ci-wd-test-runner.yml

    name: wd_test_runner
    
    on: workflow_dispatch
    
    permissions:
      actions: write
    
    jobs:
      ci:
        runs-on: ubuntu-latest
    
        steps:
        - name: Run
          env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          run: |
            gh --version
            gh workflow run ci-wd-test.yml --repo iamazeem/test

    .github/workflows/ci-wd-test.yml

    name: wd_test
    
    on: workflow_dispatch
    
    jobs:
      ci:
        runs-on: ubuntu-latest
    
        steps:
        - name: Test
          run: echo

    Workflow runs:

    gh version

    $ gh version 2.67.0 (2025-02-11)
    https://github.com/cli/cli/releases/tag/v2.67.0

    I agree that an error should be returned from the non-404 branch.
    Just want to understand the root cause. 🤔

  5. catsby commented on Feb 28, 2025

    @catsby
    Author

    Hey @iamazeem - thanks for putting a example together! I'm not able to try it out at this time but hopefully later today I can try it. It looks just like my description, the only difference notice is that in my example I don't use the --repo flag so maybe that's a clue.

    Got 404 and 403 but no panic

    That's curious... I wonder how this getWorkflowByID() method is returning a 403 error, but you are not getting a nil pointer dereference 🤔 unless I'm just misunderstanding some workflow or codepath somewhere.

    https://github.com/cli/cli/blob/817eeb26e567de11007c8a82c25e61c7e20e4337/pkg/cmd/workflow/shared/shared.go#L155C6-L164

  6. iamazeem commented on Feb 28, 2025

    @iamazeem
    Contributor

    @catsby: Sure, thank you! 👍

    the only difference notice is that in my example I don't use the --repo flag so maybe that's a clue

    I'm not using a checkout step that's why --repo flag is there.
    Doesn't seem related though.
    I'll verify it later.


    I wonder how this getWorkflowByID() method is returning a 403 error

    403 here is not from the same path.

    Earlier, you mentioned that:

    maybe the getWorkflowByID() call is returning a 403 or something due to the token being used?

    So, I deliberately missed permissions to generate a 403 error for the default GITHUB_TOKEN.
    It did generate the 403 error but no panic.


    Update

    • Tried using an invalid (non-existent) workflow filename with gh workflow run command from the runner workflow.
    • Updated both workflows for the tag_name input as described in your example.

    Both worked fine as expected i.e. failure and success respectively.

  7. catsby commented on Feb 28, 2025

    @catsby
    Author

    @iamazeem I used your examples to make my own reproduction and found similar results, but with a twist..

    403 here is not from the same path.

    This comment confused me because I couldn't see how you were hitting this method in shared.go where the panic was coming from, you were getting a 403 and no error...

    Sure enough though I got a 403 when I reproduced this on a public test repo that I made. Therein lies the issue I suppose, in something I overlooked in my initial report: I'm encountering this panic on an private/internal repo, not a public one. As soon as I made my test repo internal I got the panic again. My apologies to all for not including that detail, it didn't even occur to me that it would make a difference.

    My testing runs are at https://github.com/catsby/gh_panic_test/actions , you can ignore runs 1-2 as I didn't have things configured right.

    Run 3 shows the 403, with some other error message I didn't bother to investigate because the 403 was what I was not expecting but also looking for.

    Run 4 was done after I made the repo private/internal. There you can see the panic!

    Run 5 was done after I made the repo public again, and is the same results as Run 3.

  8. jtmcg commented on Feb 28, 2025

    @jtmcg
    Contributor

    Hey y'all, we appreciate the investigation!

    While you've been digging into this, I've been writing a fix. Well, I've mostly been writing tests to cover this part of the code, as the fix was easy 😅

    I've got a PR up for this.

    @catsby, we aren't planning on doing a patch release for this as the issue is fairly isolated, but we will be releasing on Monday or Tuesday next week and I'll make sure this fix gets in. I hope that's not too disruptive for you.

  9. self-assigned this
    on Feb 28, 2025
  10. catsby commented on Feb 28, 2025

    @catsby
    Author

    @jtmcg awesome, thanks for the fast turnaround. No worries about releasing it later, I already changed my workflows to use the reusable approach which makes more sense anyway so I'm not blocked or anything.

    Cheers!

  11. andyfeller commented on Mar 7, 2025

    @andyfeller
    Contributor

    Short term workaround until the latest GitHub Actions hosted runner image is updated

    As of March 7th, the GitHub Actions runner images, which are rebuilt weekly, have v2.67.0 installed. If you need a temporary workaround, you can install the latest version within a workflow:

          - name: Upgrade to latest gh release
            run: |
              (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
              	&& sudo mkdir -p -m 755 /etc/apt/keyrings \
                      && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
                      && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
              	&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
              	&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
              	&& sudo apt update \
              	&& sudo apt install gh -y

    In the example above, this step will setup the GitHub CLI Apt package repo to install the latest for a ubuntu-latest workflow.

    actions/runner-images uses a different process for downloading and installing GitHub CLI that doesn't rely upon Apt repository, which is why you cannot simple sudo apt upgrade gh.

    Note

    New GitHub Actions runner images should be built early next week.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggh-workflowrelating to the gh workflow commandpriority-2Affects more than a few users but doesn't prevent core functions

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions